3ddb79beNQVrdGyoI4njXhgAjD6a4A xen/drivers/block/genhd.c
3ddb79beyWwLRP_BiM2t1JKgr_plEw xen/drivers/block/ll_rw_blk.c
3e4a8cb7RhubVgsPwO7cK0pgAN8WCQ xen/drivers/block/xen_block.c
-3f045882spujO81dMl-fYWGiZ8WcPw xen/drivers/block/xen_physdisk.c
-3e5d129asHNyZOjBKTkqs-9AFzxemA xen/drivers/block/xen_segment.c
+3e5d129asHNyZOjBKTkqs-9AFzxemA xen/drivers/block/xen_vbd.c
3e9c248afxxsnAzIt2na7Ej24yNFzg xen/drivers/cdrom/Makefile
3e9c248ajUkn2W3n4vgm72Hp2ftZ8A xen/drivers/cdrom/cdrom.c
3e4a8cb7alzQCDKS7MlioPoHBKYkdQ xen/drivers/char/Makefile
3ddb79c25UE59iu4JJcbRalx95mvcg xen/include/hypervisor-ifs/hypervisor-if.h
3ead095dE_VF-QA88rl_5cWYRWtRVQ xen/include/hypervisor-ifs/kbd.h
3ddb79c2oRPrzClk3zbTkRHlpumzKA xen/include/hypervisor-ifs/network.h
-3f0d22cbroqp_BkoDPwkfRJhaw1LiQ xen/include/hypervisor-ifs/segment.h
+3f0d22cbroqp_BkoDPwkfRJhaw1LiQ xen/include/hypervisor-ifs/vbd.h
3ddb79c4qbCoOFHrv9sCGshbWzBVlQ xen/include/scsi/scsi.h
3ddb79c4R4iVwqIIeychVQYmIH4FUg xen/include/scsi/scsi_ioctl.h
3ddb79c4yw_mfd4Uikn3v_IOPRpa1Q xen/include/scsi/scsicam.h
3ddb79c0nTsjSpVK4ZVTI9WwN24xtQ xen/include/xeno/blk.h
3ddb79c0dVhTHLsv6CPTf4baKix4mA xen/include/xeno/blkdev.h
3ddb79c18ePBgitnOs7GiOCFilODVw xen/include/xeno/blkpg.h
-3ddb79c2SisDOHDyTeK5-MV3m7pNbA xen/include/xeno/block.h
3ddb79c1oOjpQbp68MW7yiUpoi-S-w xen/include/xeno/brlock.h
3ddb79c1x7Ie3kifu7dQRx8y7HVyvA xen/include/xeno/byteorder/big_endian.h
3ddb79c1qFXOEX1eD0yXJ_gsGkUt8w xen/include/xeno/byteorder/generic.h
3ddb79c0MOVXq8qZDQRGb6z64_xAwg xen/include/xeno/pci_ids.h
3e54c38dlSCVdyVM4PKcrSfzLLxWUQ xen/include/xeno/perfc.h
3e54c38de9SUSYSAwxDf_DwkpAnQFA xen/include/xeno/perfc_defn.h
-3f055a3dwldYR102YcSuBaxIf9t3Jw xen/include/xeno/physdisk.h
3ddb79c04nQVR3EYM5L4zxDV_MCo1g xen/include/xeno/prefetch.h
3e4540ccU1sgCx8seIMGlahmMfv7yQ xen/include/xeno/reboot.h
3ddb79c0LzqqS0LhAQ50ekgj4oGl7Q xen/include/xeno/sched.h
-3e5d129a2bbGTpVSZFN_mAnbm97ixw xen/include/xeno/segment.h
3ddb79c0VDeD-Oft5eNfMneTU3D1dQ xen/include/xeno/skbuff.h
3ddb79c14dXIhP7C2ahnoD08K90G_w xen/include/xeno/slab.h
3ddb79c09xbS-xxfKxuV3JETIhBzmg xen/include/xeno/smp.h
3ddb79c2_m8lT9jDKse_tePj7zcnNQ xen/include/xeno/timex.h
3ddb79c2e2C14HkndNEJlYwXaPrF5A xen/include/xeno/tqueue.h
3ddb79c1-kVvF8cVa0k3ZHDdBMj01Q xen/include/xeno/types.h
+3f055a3dwldYR102YcSuBaxIf9t3Jw xen/include/xeno/vbd.h
3e8827bdaqPeZAWGVOwswgY9bWSx4g xen/include/xeno/version.h
3ddb79c2Ae5KpzhC9LCYG7mP_Vi4Aw xen/include/xeno/vif.h
3ddb79c4YQCQ6r0xNLLu0jfbM7pVmA xen/net/Makefile
3e67f822FOPwqHiaRKbrskgWgoNL5g xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_block.h
3e677190SjkzJIvFifRVeYpIZOCtYA xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_ide.c
3e677193nOKKTLJzcAu4SYdbZaia8g xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_scsi.c
-3e676eb5RXnHzSHgA1BvM0B1aIm4qg xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_segment.c
-3e5d129aDldt6geU2-2SzBae34sQzg xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_segment_proc.c
+3e676eb5RXnHzSHgA1BvM0B1aIm4qg xenolinux-2.4.22-sparse/arch/xeno/drivers/block/xl_vbd.c
3e5a4e65G3e2s0ghPMgiJ-gBTUJ0uQ xenolinux-2.4.22-sparse/arch/xeno/drivers/console/Makefile
3e5a4e651TH-SXHoufurnWjgl5bfOA xenolinux-2.4.22-sparse/arch/xeno/drivers/console/console.c
3e5a4e656nfFISThfbyXQOA6HN6YHw xenolinux-2.4.22-sparse/arch/xeno/drivers/dom0/Makefile
#include <asm-xeno/proc_cmd.h>
#include <hypervisor-ifs/hypervisor-if.h>
#include <hypervisor-ifs/dom0_ops.h>
+#include <hypervisor-ifs/vbd.h>
#define ERROR(_m) \
fprintf(stderr, "ERROR: %s\n", (_m))
#include <asm/msr.h>
#include <xeno/blkdev.h>
#include <xeno/console.h>
-#include <hypervisor-ifs/block.h>
-#include <xeno/physdisk.h>
+#include <xeno/vbd.h>
/*
* NB. No ring-3 access in initial guestOS pagetables. Note that we allow
unlink_blkdev_info(p);
- for ( i = 0; i < XEN_MAX_SEGMENTS; i++ )
- xen_segment_delete(p, i);
+ for ( i = 0; i < XEN_MAX_VBDS; i++ )
+ xen_vbd_delete(p, i);
for ( i = 0; i < MAX_DOMAIN_VIFS; i++ )
unlink_net_vif(p->net_vif_list[i]);
#include <hypervisor-ifs/block.h>
#include <hypervisor-ifs/hypervisor-if.h>
#include <asm-i386/io.h>
+#include <asm/domain_page.h>
#include <xeno/spinlock.h>
#include <xeno/keyhandler.h>
#include <xeno/interrupt.h>
-#include <xeno/segment.h>
+#include <xeno/vbd.h>
#include <xeno/slab.h>
-#include <xeno/physdisk.h>
#if 0
#define DPRINTK(_f, _a...) printk( _f , ## _a )
static void io_schedule(unsigned long unused);
static int do_block_io_op_domain(struct task_struct *p, int max_to_do);
static void dispatch_rw_block_io(struct task_struct *p, int index);
-static void dispatch_probe_blk(struct task_struct *p, int index);
-static void dispatch_probe_seg(struct task_struct *p, int index);
-static void dispatch_probe_seg_all(struct task_struct *p, int index);
+static void dispatch_probe(struct task_struct *p, int index);
static void dispatch_debug_block_io(struct task_struct *p, int index);
-static void dispatch_create_segment(struct task_struct *p, int index);
-static void dispatch_delete_segment(struct task_struct *p, int index);
+static void dispatch_create_vbd(struct task_struct *p, int index);
+static void dispatch_delete_vbd(struct task_struct *p, int index);
static void dispatch_grant_physdev(struct task_struct *p, int index);
static void dispatch_probe_physdev(struct task_struct *p, int index);
static void make_response(struct task_struct *p, unsigned long id,
}
+long vbd_attach(vbd_attach_t *info)
+{
+ printk("vbd_attach called!!!\n");
+ return -ENOSYS;
+}
-/******************************************************************
- * GUEST-OS SYSCALL -- Indicates there are requests outstanding.
- */
+/* ----[ Syscall Interface ]------------------------------------------------*/
-long do_block_io_op(void)
+long do_block_io_op(block_io_op_t *u_block_io_op)
{
- add_to_blkdev_list_tail(current);
- maybe_trigger_io_schedule();
- return 0L;
+ long ret = 0;
+ block_io_op_t op;
+
+ if (copy_from_user(&op, u_block_io_op, sizeof(op)))
+ return -EFAULT;
+
+ switch (op.cmd) {
+
+ case BLOCK_IO_OP_SIGNAL:
+ /* simply indicates there're reqs outstanding => add current to list */
+ add_to_blkdev_list_tail(current);
+ maybe_trigger_io_schedule();
+ break;
+
+ case BLOCK_IO_OP_ATTACH_VBD:
+ /* attach a VBD to a given domain; caller must be privileged */
+ if(!IS_PRIV(current))
+ return -EPERM;
+ ret = vbd_attach(&op.u.attach_info);
+ break;
+
+ default:
+ ret = -ENOSYS;
+ }
+
+
+ return ret;
}
dispatch_rw_block_io(p, i);
break;
- case XEN_BLOCK_PROBE_BLK:
- dispatch_probe_blk(p, i);
- break;
-
- case XEN_BLOCK_PROBE_SEG:
- dispatch_probe_seg(p, i);
- break;
-
- case XEN_BLOCK_PROBE_SEG_ALL:
- dispatch_probe_seg_all(p, i);
+ case XEN_BLOCK_PROBE:
+ dispatch_probe(p, i);
break;
case XEN_BLOCK_DEBUG:
dispatch_debug_block_io(p, i);
break;
- case XEN_BLOCK_SEG_CREATE:
- dispatch_create_segment(p, i);
+ case XEN_BLOCK_VBD_CREATE:
+ dispatch_create_vbd(p, i);
break;
- case XEN_BLOCK_SEG_DELETE:
- dispatch_delete_segment(p, i);
+ case XEN_BLOCK_VBD_DELETE:
+ dispatch_delete_vbd(p, i);
break;
case XEN_BLOCK_PHYSDEV_GRANT:
XEN_BLOCK_PHYSDEV_GRANT, result);
}
-static void dispatch_create_segment(struct task_struct *p, int index)
+static void dispatch_create_vbd(struct task_struct *p, int index)
{
blk_ring_t *blk_ring = p->blk_ring_base;
unsigned long flags, buffer;
if ( p->domain != 0 )
{
- DPRINTK("dispatch_create_segment called by dom%d\n", p->domain);
+ DPRINTK("dispatch_create_vbd called by dom%d\n", p->domain);
result = 1;
goto out;
}
spin_lock_irqsave(&p->page_lock, flags);
if ( !__buffer_is_valid(p, buffer, sizeof(xv_disk_t), 1) )
{
- DPRINTK("Bad buffer in dispatch_create_segment\n");
+ DPRINTK("Bad buffer in dispatch_create_vbd\n");
spin_unlock_irqrestore(&p->page_lock, flags);
result = 1;
goto out;
spin_unlock_irqrestore(&p->page_lock, flags);
xvd = phys_to_virt(buffer);
- result = xen_segment_create(xvd);
+ result = xen_vbd_create(xvd);
unlock_buffer(p, buffer, sizeof(xv_disk_t), 1);
out:
make_response(p, blk_ring->ring[index].req.id,
- XEN_BLOCK_SEG_CREATE, result);
+ XEN_BLOCK_VBD_CREATE, result);
}
-static void dispatch_delete_segment(struct task_struct *p, int index)
+static void dispatch_delete_vbd(struct task_struct *p, int index)
{
- DPRINTK("dispatch_delete_segment: unimplemented\n");
+ DPRINTK("dispatch_delete_vbd: unimplemented\n");
}
-static void dispatch_probe_blk(struct task_struct *p, int index)
+static void dispatch_probe(struct task_struct *p, int index)
{
extern void ide_probe_devices(xen_disk_info_t *xdi);
extern void scsi_probe_devices(xen_disk_info_t *xdi);
+ extern void vbd_probe_devices(xen_disk_info_t *xdi, struct task_struct *p);
blk_ring_t *blk_ring = p->blk_ring_base;
xen_disk_info_t *xdi;
rc = 1;
goto out;
}
- __lock_buffer(buffer, sizeof(xen_disk_info_t), 1);
- spin_unlock_irqrestore(&p->page_lock, flags);
-
- xdi = phys_to_virt(buffer);
- ide_probe_devices(xdi);
- scsi_probe_devices(xdi);
-
- unlock_buffer(p, buffer, sizeof(xen_disk_info_t), 1);
-
- out:
- make_response(p, blk_ring->ring[index].req.id, XEN_BLOCK_PROBE_BLK, rc);
-}
-
-static void dispatch_probe_seg(struct task_struct *p,
- int index)
-{
- extern void xen_segment_probe(struct task_struct *, xen_disk_info_t *);
-
- blk_ring_t *blk_ring = p->blk_ring_base;
- xen_disk_info_t *xdi;
- unsigned long flags, buffer;
- int rc = 0;
- buffer = blk_ring->ring[index].req.buffer_and_sects[0] & ~0x1FF;
-
- spin_lock_irqsave(&p->page_lock, flags);
- if ( !__buffer_is_valid(p, buffer, sizeof(xen_disk_info_t), 1) )
- {
- DPRINTK("Bad buffer in dispatch_probe_seg\n");
- spin_unlock_irqrestore(&p->page_lock, flags);
- rc = 1;
- goto out;
- }
__lock_buffer(buffer, sizeof(xen_disk_info_t), 1);
spin_unlock_irqrestore(&p->page_lock, flags);
- xdi = phys_to_virt(buffer);
- xen_segment_probe(p, xdi);
+ /*
+ ** XXX SMH: all three of the below probe functions /append/ their
+ ** info to the xdi array; i.e. they assume that all earlier slots
+ ** are correctly filled, and that xdi->count points to the first
+ ** free entry in the array. All kinda gross but it'll do for now.
+ */
+ xdi = map_domain_mem(buffer);
+ xdi->count = 0;
+ if(IS_PRIV(p)) {
+ /* privilege domains always gets access to the 'real' devices */
+ ide_probe_devices(xdi);
+ scsi_probe_devices(xdi);
+ }
+ vbd_probe_devices(xdi, p);
+ unmap_domain_mem(xdi);
unlock_buffer(p, buffer, sizeof(xen_disk_info_t), 1);
out:
- make_response(p, blk_ring->ring[index].req.id, XEN_BLOCK_PROBE_SEG, rc);
-}
-
-static void dispatch_probe_seg_all(struct task_struct *p, int index)
-{
- extern void xen_segment_probe_all(xen_segment_info_t *);
-
- blk_ring_t *blk_ring = p->blk_ring_base;
- xen_segment_info_t *xsi;
- unsigned long flags, buffer;
- int rc = 0;
-
- buffer = blk_ring->ring[index].req.buffer_and_sects[0] & ~0x1FF;
-
- spin_lock_irqsave(&p->page_lock, flags);
- if ( !__buffer_is_valid(p, buffer, sizeof(xen_segment_info_t), 1) )
- {
- DPRINTK("Bad buffer in dispatch_probe_seg_all\n");
- spin_unlock_irqrestore(&p->page_lock, flags);
- rc = 1;
- goto out;
- }
- __lock_buffer(buffer, sizeof(xen_segment_info_t), 1);
- spin_unlock_irqrestore(&p->page_lock, flags);
-
- xsi = phys_to_virt(buffer);
- xen_segment_probe_all(xsi);
-
- unlock_buffer(p, buffer, sizeof(xen_segment_info_t), 1);
-
- out:
- make_response(p, blk_ring->ring[index].req.id, XEN_BLOCK_PROBE_SEG_ALL, rc);
+ make_response(p, blk_ring->ring[index].req.id, XEN_BLOCK_PROBE, rc);
}
static void dispatch_rw_block_io(struct task_struct *p, int index)
/* Get the physical device and block index. */
if ( (req->device & XENDEV_TYPE_MASK) == XENDEV_VIRTUAL )
{
- new_segs = xen_segment_map_request(
+ new_segs = xen_vbd_map_request(
&phys_seg[nr_psegs], p, operation,
req->device,
req->sector_number + tot_sects,
buffer, nr_sects);
if ( new_segs <= 0 )
{
- DPRINTK("bogus xen_segment_map_request\n");
+ DPRINTK("bogus xen_vbd_map_request\n");
goto bad_descriptor;
}
}
SHARE_PFN_WITH_DOMAIN(virt_to_page(p->blk_ring_base), p->domain);
p->blkdev_list.next = NULL;
- memset(p->segment_list, 0, sizeof(p->segment_list));
+ memset(p->vbd_list, 0, sizeof(p->vbd_list));
/* Get any previously created segments. */
- xen_refresh_segment_list(p);
+ xen_refresh_vbd_list(p);
}
/* End-of-day teardown for a domain. */
"buffer_head_cache", sizeof(struct buffer_head),
0, SLAB_HWCACHE_ALIGN, NULL, NULL);
- xen_segment_initialize();
+ xen_vbd_initialize();
add_key_handler('b', dump_blockq, "dump xen ide blkdev statistics");
}
+++ /dev/null
-#include <xeno/sched.h>
-#include <xeno/list.h>
-#include <xeno/blkdev.h>
-#include <xeno/sched.h>
-#include <xeno/slab.h>
-#include <asm/domain_page.h>
-#include <asm/io.h>
-#include <xeno/segment.h>
-#include <xeno/physdisk.h>
-
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
-#if 0
-#define DPRINTK printk
-#else
-#define DPRINTK(...)
-#endif
-
-/* The idea is that, for each sector of each disk, each domain has two
- bits, saying whether they can read the sector or write it. That
- would take too much memory, so instead each process has a list of
- (device, start, end, mode) quads which say what it has access to,
- and we fake the logical view on top of that. */
-struct physdisk_ace {
- struct list_head list;
- unsigned short device;
- unsigned short partition;
- unsigned long start_sect;
- unsigned long n_sectors;
- int mode;
-};
-
-/* Operation is a blkdev constant i.e. READ, WRITE, ... */
-/* Must be called with p->physdev_lock held. */
-static struct physdisk_ace *find_ace(const struct task_struct *p,
- unsigned short dev,
- unsigned long sect, int operation)
-{
- struct list_head *cur_ace_head;
- struct physdisk_ace *cur_ace;
-
- list_for_each(cur_ace_head, &p->physdisk_aces)
- {
- cur_ace = list_entry(cur_ace_head, struct physdisk_ace, list);
- DPRINTK("Is [%lx, %lx) good for %lx?\n",
- cur_ace->start_sect,
- cur_ace->start_sect + cur_ace->n_sectors, sect);
- if ( (sect >= cur_ace->start_sect) &&
- (sect < (cur_ace->start_sect + cur_ace->n_sectors)) &&
- (dev == cur_ace->device) &&
- (((operation == READ) && (cur_ace->mode & PHYSDISK_MODE_R)) ||
- ((operation == WRITE) && (cur_ace->mode & PHYSDISK_MODE_W))) )
- return cur_ace;
- }
- return NULL;
-}
-
-/* Hold the lock on entry, it remains held on exit. */
-static void xen_physdisk_revoke_access(unsigned short dev,
- unsigned long start_sect,
- unsigned long n_sectors,
- struct task_struct *p)
-{
- /* Find every ace which intersects [start_sect, start_sect +
- n_sectors] and either remove it completely or truncate it
- down. */
- struct list_head *cur_ace_head;
- struct physdisk_ace *cur_ace, *new_ace;
- unsigned long kill_zone_end, ace_end;
-
- kill_zone_end = start_sect + n_sectors;
- list_for_each(cur_ace_head, &p->physdisk_aces)
- {
- cur_ace = list_entry(cur_ace_head, struct physdisk_ace, list);
- ace_end = cur_ace->start_sect + cur_ace->n_sectors;
- if ( (cur_ace->start_sect >= kill_zone_end) ||
- (ace_end <= start_sect) ||
- (cur_ace->device != dev) )
- continue;
-
- DPRINTK("Killing ace [%lx, %lx) against kill zone [%lx, %lx)\n",
- cur_ace->start_sect, ace_end, start_sect, kill_zone_end);
-
- if ( (cur_ace->start_sect >= start_sect) &&
- (ace_end <= kill_zone_end) )
- {
- /* ace entirely within kill zone -> kill it */
- list_del(cur_ace_head);
- cur_ace_head = cur_ace_head->prev;
- kfree(cur_ace);
- }
- else if ( ace_end <= kill_zone_end )
- {
- /* ace start before kill start, ace end in kill zone,
- move ace end. */
- cur_ace->n_sectors = start_sect - cur_ace->start_sect;
- }
- else if ( cur_ace->start_sect >= start_sect )
- {
- /* ace start after kill start, ace end outside kill zone,
- move ace start. */
- cur_ace->start_sect = kill_zone_end;
- cur_ace->n_sectors = ace_end - cur_ace->start_sect;
- }
- else
- {
- /* The fun one: the ace entirely includes the kill zone. */
- /* Cut the current ace down to just the bit before the kzone,
- create a new ace for the bit just after it. */
- new_ace = kmalloc(sizeof(*cur_ace), GFP_KERNEL);
- new_ace->device = dev;
- new_ace->start_sect = kill_zone_end;
- new_ace->n_sectors = ace_end - kill_zone_end;
- new_ace->mode = cur_ace->mode;
-
- cur_ace->n_sectors = start_sect - cur_ace->start_sect;
-
- list_add(&new_ace->list, cur_ace_head);
- }
- }
-}
-
-/* Hold the lock on entry, it remains held on exit. */
-static int xen_physdisk_grant_access(unsigned short dev,
- unsigned short partition,
- unsigned long start_sect,
- unsigned long n_sectors,
- int mode, struct task_struct *p)
-{
- struct physdisk_ace *cur_ace;
-
- /* Make sure it won't overlap with any existing ACEs. */
- /* XXX this isn't quite right if the domain already has read access
- and we try to grant write access, or vice versa. */
- xen_physdisk_revoke_access(dev, start_sect, n_sectors, p);
-
- if ( mode )
- {
- cur_ace = kmalloc(sizeof(*cur_ace), GFP_KERNEL);
- cur_ace->device = dev;
- cur_ace->start_sect = start_sect;
- cur_ace->n_sectors = n_sectors;
- cur_ace->mode = mode;
- cur_ace->partition = partition;
-
- list_add_tail(&cur_ace->list, &p->physdisk_aces);
- }
-
- return 0;
-}
-
-static void xen_physdisk_probe_access(physdisk_probebuf_t * buf,
- struct task_struct *p)
-{
- int n_aces;
- struct list_head *cur_ace_head;
- struct physdisk_ace *cur_ace;
- int x = 0;
-
- n_aces = 0;
- list_for_each(cur_ace_head, &p->physdisk_aces)
- {
- x++;
- if ( x >= buf->start_ind )
- {
- cur_ace = list_entry(cur_ace_head, struct physdisk_ace, list);
- buf->entries[n_aces].device = cur_ace->device;
- buf->entries[n_aces].partition = cur_ace->partition;
- buf->entries[n_aces].start_sect = cur_ace->start_sect;
- buf->entries[n_aces].n_sectors = cur_ace->n_sectors;
- buf->entries[n_aces].mode = cur_ace->mode;
- n_aces++;
- }
- }
- buf->n_aces = n_aces;
-}
-
-int xen_physdisk_grant(xp_disk_t * xpd_in)
-{
- struct task_struct *p = current;
- xp_disk_t *xpd = map_domain_mem(virt_to_phys(xpd_in));
- int res;
-
- p = find_domain_by_id(xpd->domain);
- if ( p == NULL )
- {
- DPRINTK("Bad domain!\n");
- res = 1;
- goto out;
- }
-
- spin_lock(&p->physdev_lock);
- res = xen_physdisk_grant_access(xpd->device,
- xpd->partition,
- xpd->start_sect,
- xpd->n_sectors, xpd->mode, p);
- spin_unlock(&p->physdev_lock);
- put_task_struct(p);
-
- out:
- unmap_domain_mem(xpd);
- return res;
-}
-
-int xen_physdisk_probe(struct task_struct *requesting_domain,
- physdisk_probebuf_t * buf_in)
-{
- struct task_struct *p;
- physdisk_probebuf_t *buf = map_domain_mem(virt_to_phys(buf_in));
- int res;
-
- if ( (requesting_domain->domain != 0) &&
- (requesting_domain->domain != buf->domain) )
- {
- res = 1;
- goto out;
- }
-
- p = find_domain_by_id(buf->domain);
- if ( p == NULL )
- {
- res = 1;
- goto out;
- }
-
- spin_lock(&p->physdev_lock);
- xen_physdisk_probe_access(buf, p);
- spin_unlock(&p->physdev_lock);
- put_task_struct(p);
-
- res = 0;
- out:
- unmap_domain_mem(buf);
- return res;
-}
-
-int xen_physdisk_access_okay(phys_seg_t * pseg, struct task_struct *p,
- int operation)
-{
- struct physdisk_ace *cur_ace;
- unsigned long sect;
-
- DPRINTK
- ("Checking access for domain %d, start sect 0x%lx, length 0x%x.\n",
- p->domain, pseg->sector_number, pseg->nr_sects);
-
- for ( sect = pseg->sector_number;
- sect < pseg->sector_number + pseg->nr_sects; )
- {
- /* XXX this would be a lot faster if the aces were sorted on start
- address. Also in revoke_access. */
- spin_lock(&p->physdev_lock);
- cur_ace = find_ace(p, pseg->dev, sect, operation);
- spin_unlock(&p->physdev_lock);
- if ( cur_ace == NULL )
- return 0;
- sect +=
- MAX(cur_ace->n_sectors,
- pseg->nr_sects + pseg->sector_number - sect);
- }
- return 1;
-}
-
-void destroy_physdisk_aces(struct task_struct *p)
-{
- struct list_head *cur_ace_head, *next_head;
- struct physdisk_ace *cur_ace;
-
- for ( cur_ace_head = p->physdisk_aces.next;
- cur_ace_head != &p->physdisk_aces;
- cur_ace_head = next_head )
- {
- cur_ace = list_entry(cur_ace_head, struct physdisk_ace, list);
- next_head = cur_ace_head->next;
- kfree(cur_ace);
- }
-}
+++ /dev/null
-/*
- * xen_segment.c
- */
-
-#include <xeno/config.h>
-#include <xeno/types.h>
-#include <xeno/lib.h>
-#include <asm/io.h>
-#include <xeno/slab.h>
-#include <xeno/segment.h>
-#include <xeno/sched.h>
-#include <xeno/blkdev.h>
-#include <xeno/keyhandler.h>
-#include <asm/current.h>
-#include <asm/domain_page.h>
-#include <hypervisor-ifs/block.h>
-
-/* Global list of all possible segments. This can be changed in
- the following way:
-
- 1) UNUSED segment -> RO or RW segment. This requires the spinlock.
-
- 2) RO or RW -> UNUSED. This requires the lock and can only happen
- during process teardown.
-
- This means that processes can access entries in the list safely
- without having to hold any lock at all: they already have an entry
- allocated, and we know that entry can't become unused, as segments
- are only torn down when the domain is dieing, by which point it
- can't be accessing them anymore. */
-static segment_t xsegments[XEN_MAX_SEGMENTS];
-static spinlock_t xsegment_lock = SPIN_LOCK_UNLOCKED;
-
-#if 0
-#define DPRINTK(_f, _a...) printk( _f , ## _a )
-#else
-#define DPRINTK(_f, _a...) ((void)0)
-#endif
-
-/*
- * xen_segment_map_request
- *
- * xen_device must be a valid device.
- *
- * NB. All offsets and sizes here are in sector units.
- * eg. 'size == 1' means an actual size of 512 bytes.
- *
- * Note that no locking is performed here whatsoever --
- * we rely on the fact that once segment information is
- * established, it is only modified by domain shutdown,
- * and so if this is being called, noone is trying
- * to modify the segment list.
- */
-int xen_segment_map_request(
- phys_seg_t *pseg, struct task_struct *p, int operation,
- unsigned short segment_number,
- unsigned long sect_nr, unsigned long buffer, unsigned short nr_sects)
-{
- segment_t *seg;
- extent_t *ext;
- int sum, i;
-
- segment_number &= XENDEV_IDX_MASK;
- if ( segment_number >= XEN_MAX_SEGMENTS )
- {
- DPRINTK("invalid segment number. %d %d\n",
- segment_number, XEN_MAX_SEGMENTS);
- goto fail;
- }
-
- seg = p->segment_list[segment_number];
- if ( seg == NULL )
- {
- DPRINTK("segment is null. %d\n", segment_number);
- goto fail;
- }
-
- /* check domain permissions */
- if ( seg->domain != p->domain )
- {
- DPRINTK("seg is for another domain. %d %d\n", seg->domain, p->domain);
- goto fail;
- }
-
- /* check rw access */
- if ( ((operation == WRITE) && (seg->mode != XEN_SEGMENT_RW)) ||
- ((operation == READ) && (seg->mode == XEN_SEGMENT_UNUSED)) )
- {
- DPRINTK("illegal operation: %d %d\n", operation, seg->mode);
- goto fail;
- }
-
- if ( (nr_sects + sect_nr) <= sect_nr )
- {
- DPRINTK("sector + size wrap! %08lx %04x\n", sect_nr, nr_sects);
- goto fail;
- }
-
- /* find extent, check size */
- sum = 0;
- i = 0;
- ext = seg->extents;
- while ( (i < seg->num_extents) && ((sum + ext->size) <= sect_nr) )
- {
- sum += ext->size;
- ext++; i++;
- }
-
- if ( (sum + ext->size) <= sect_nr )
- {
- DPRINTK("extent size mismatch: %d %d : %d %ld %ld\n",
- i, seg->num_extents, sum, ext->size, sect_nr);
- goto fail;
- }
-
- pseg->sector_number = (sect_nr - sum) + ext->offset;
- pseg->buffer = buffer;
- pseg->nr_sects = nr_sects;
- pseg->dev = xendev_to_physdev(ext->disk);
- if ( pseg->dev == 0 )
- {
- DPRINTK ("invalid device 0x%x 0x%lx 0x%lx\n",
- ext->disk, ext->offset, ext->size);
- goto fail;
- }
-
- /* We're finished if the virtual extent didn't overrun the phys extent. */
- if ( (sum + ext->size) >= (sect_nr + nr_sects) )
- return 1; /* entire read fits in this extent */
-
- /* Hmmm... make sure there's another extent to overrun onto! */
- if ( (i+1) == seg->num_extents )
- {
- DPRINTK ("not enough extents %d %d\n",
- i, seg->num_extents);
- goto fail;
- }
-
- pseg[1].nr_sects = (sect_nr + nr_sects) - (sum + ext->size);
- pseg[0].nr_sects = sum + ext->size - sect_nr;
- pseg[1].buffer = buffer + (pseg->nr_sects << 9);
- pseg[1].sector_number = ext[1].offset;
- pseg[1].dev = xendev_to_physdev(ext[1].disk);
- if ( pseg[1].dev == 0 )
- {
- DPRINTK ("bogus device for pseg[1] \n");
- goto fail;
- }
-
- /* We don't allow overrun onto a third physical extent. */
- if ( pseg[1].nr_sects > ext[1].size )
- {
- DPRINTK ("third extent\n");
- DPRINTK (" sum:%d, e0:%ld, e1:%ld p1.sect:%ld p1.nr:%d\n",
- sum, ext[0].size, ext[1].size,
- pseg[1].sector_number, pseg[1].nr_sects);
- goto fail;
- }
-
- return 2; /* We overran onto a second physical extent. */
-
- fail:
- DPRINTK ("xen_segment_map_request failure\n");
- DPRINTK ("operation: %d\n", operation);
- DPRINTK ("segment number: %d\n", segment_number);
- DPRINTK ("sect_nr: %ld 0x%lx\n", sect_nr, sect_nr);
- DPRINTK ("nr_sects: %d 0x%x\n", nr_sects, nr_sects);
- return -1;
-}
-
-/*
- * xen_segment_probe
- *
- * return a list of segments to the guestos
- */
-void xen_segment_probe(struct task_struct *p, xen_disk_info_t *raw_xdi)
-{
- int loop, i;
- xen_disk_info_t *xdi = map_domain_mem(virt_to_phys(raw_xdi));
- unsigned long capacity = 0, device;
-
- spin_lock(&xsegment_lock);
- xdi->count = 0;
- for ( loop = 0; loop < XEN_MAX_SEGMENTS; loop++ )
- {
- if ( (xsegments[loop].mode == XEN_SEGMENT_UNUSED) ||
- (xsegments[loop].domain != p->domain) )
- continue;
-
- device = MK_VIRTUAL_XENDEV(xsegments[loop].segment_number);
- for ( i = 0; i < xsegments[loop].num_extents; i++ )
- capacity += xsegments[loop].extents[i].size;
-
- xdi->disks[xdi->count].device = device;
- xdi->disks[xdi->count].capacity = capacity;
- xdi->count++;
- }
- spin_unlock(&xsegment_lock);
-
- unmap_domain_mem(xdi);
-}
-
-/*
- * xen_segment_probe_all
- *
- * return a list of all segments to domain 0
- */
-void xen_segment_probe_all(xen_segment_info_t *raw_xsi)
-{
- int loop;
- xen_segment_info_t *xsi = map_domain_mem(virt_to_phys(raw_xsi));
-
- spin_lock(&xsegment_lock);
- xsi->count = 0;
- for ( loop = 0; loop < XEN_MAX_SEGMENTS; loop++ )
- {
- if ( xsegments[loop].mode == XEN_SEGMENT_UNUSED )
- continue;
-
- xsi->segments[xsi->count].mode = xsegments[loop].mode;
- xsi->segments[xsi->count].domain = xsegments[loop].domain;
- memcpy(xsi->segments[xsi->count].key,
- xsegments[loop].key,
- XEN_SEGMENT_KEYSIZE);
- xsi->segments[xsi->count].seg_nr = xsegments[loop].segment_number;
- xsi->count++;
- }
- spin_unlock(&xsegment_lock);
-
- unmap_domain_mem(xsi);
-}
-
-/*
- * xen_refresh_segment_list
- *
- * find all segments associated with a domain and assign
- * them to the domain
- *
- */
-void xen_refresh_segment_list (struct task_struct *p)
-{
- int loop;
-
- spin_lock(&xsegment_lock);
- for (loop = 0; loop < XEN_MAX_SEGMENTS; loop++)
- {
- if ( (xsegments[loop].mode == XEN_SEGMENT_UNUSED) ||
- (xsegments[loop].domain != p->domain) )
- continue;
-
- p->segment_list[xsegments[loop].segment_number] = &xsegments[loop];
- }
- spin_unlock(&xsegment_lock);
-}
-
-/*
- * create a new segment for a domain
- *
- * return 0 on success, 1 on failure
- *
- * if we see the same DOM#/SEG# combination, we reuse the slot in
- * the segment table (overwriting what was there before).
- * an alternative would be to raise an error if the slot is reused.
- */
-int xen_segment_create(xv_disk_t *xvd_in)
-{
- int idx;
- int loop;
- xv_disk_t *xvd = map_domain_mem(virt_to_phys(xvd_in));
- struct task_struct *p;
-
- spin_lock(&xsegment_lock);
- for (idx = 0; idx < XEN_MAX_SEGMENTS; idx++)
- {
- if (xsegments[idx].mode == XEN_SEGMENT_UNUSED ||
- (xsegments[idx].domain == xvd->domain &&
- xsegments[idx].segment_number == xvd->segment)) break;
- }
- if (idx == XEN_MAX_SEGMENTS)
- {
- printk (KERN_ALERT "xen_segment_create: unable to find free slot\n");
- unmap_domain_mem(xvd);
- return 1;
- }
-
- xsegments[idx].mode = xvd->mode;
- xsegments[idx].domain = xvd->domain;
- xsegments[idx].segment_number = xvd->segment;
- memcpy(xsegments[idx].key, xvd->key, XEN_SEGMENT_KEYSIZE);
- xsegments[idx].num_extents = xvd->ext_count;
-
-
- if (xsegments[idx].extents)
- kfree(xsegments[idx].extents);
- xsegments[idx].extents = (extent_t *)kmalloc(
- sizeof(extent_t)*xvd->ext_count,
- GFP_KERNEL);
-
- /* could memcpy, but this is safer */
- for (loop = 0; loop < xvd->ext_count; loop++)
- {
- xsegments[idx].extents[loop].disk = xvd->extents[loop].disk;
- xsegments[idx].extents[loop].offset = xvd->extents[loop].offset;
- xsegments[idx].extents[loop].size = xvd->extents[loop].size;
- if (xsegments[idx].extents[loop].size == 0)
- {
- printk("xen_segment_create: extent %d is zero length\n", loop);
- unmap_domain_mem(xvd);
- return 1;
- }
- }
-
- /* if the domain exists, assign the segment to the domain */
- p = find_domain_by_id(xvd->domain);
- if (p != NULL)
- {
- p->segment_list[xvd->segment] = &xsegments[idx];
- put_task_struct(p);
- }
-
- spin_unlock(&xsegment_lock);
-
- unmap_domain_mem(xvd);
- return 0;
-}
-
-/*
- * delete a segment from a domain
- *
- * return 0 on success, 1 on failure
- *
- * This should *only* be called from domain shutdown, or else we
- * race with access checking.
- */
-int xen_segment_delete(struct task_struct *p, int segnr)
-{
- segment_t *seg;
-
- if (!p) {
- printk("xen_segment delete called with NULL domain?\n");
- BUG();
- return 1;
- }
-
- if (segnr < 0 || segnr > XEN_MAX_SEGMENTS) {
- printk("xen_segment_delete called with bad segnr?\n");
- BUG();
- return 1;
- }
-
- if (!p->segment_list[segnr])
- return 1;
-
- seg = p->segment_list[segnr];
-
- /* sanity checking */
- if (seg->domain != p->domain || seg->segment_number != segnr ||
- (seg->mode != XEN_SEGMENT_RO && seg->mode != XEN_SEGMENT_RW) ||
- seg->num_extents <= 0 || seg->extents == NULL) {
- printk("segment is insane!\n");
- BUG();
- return 1;
- }
-
- spin_lock(&xsegment_lock);
-
- p->segment_list[segnr] = NULL;
- seg->domain = -1;
- seg->segment_number = -1;
- kfree(seg->extents);
- seg->mode = XEN_SEGMENT_UNUSED;
-
- spin_unlock(&xsegment_lock);
-
- return 0;
-}
-
-static void dump_segments(u_char key, void *dev_id, struct pt_regs *regs)
-{
- int loop, i;
- struct task_struct *p;
-
- printk("segment list\n");
- for (loop = 0; loop < XEN_MAX_SEGMENTS; loop++)
- {
- if (xsegments[loop].mode != XEN_SEGMENT_UNUSED)
- {
- printk(" %2d: %s dom%d, seg# %d, num_exts: %d\n",
- loop,
- xsegments[loop].mode == XEN_SEGMENT_RO ? "RO" : "RW",
- xsegments[loop].domain, xsegments[loop].segment_number,
- xsegments[loop].num_extents);
- for (i = 0; i < xsegments[loop].num_extents; i++)
- {
- printk(" extent %d: disk 0x%x, offset 0x%lx, size 0x%lx\n",
- i, xsegments[loop].extents[i].disk,
- xsegments[loop].extents[i].offset,
- xsegments[loop].extents[i].size);
- }
- }
- }
-
- printk("segments by domain (index into segments list)\n");
- p = current;
- do
- {
- printk(" domain %d: ", p->domain);
- for (loop = 0; loop < XEN_MAX_SEGMENTS; loop++)
- {
- if (p->segment_list[loop])
- {
- printk (" %d", p->segment_list[loop] - xsegments);
- }
- }
- printk("\n");
- p = p->next_task;
- } while (p != current);
-}
-
-/*
- * initialize segments
- */
-
-void xen_segment_initialize(void)
-{
- memset (xsegments, 0, sizeof(xsegments));
-
- add_key_handler('S', dump_segments, "dump segments");
-}
--- /dev/null
+/*
+ * xen_vbd.c : routines for managing virtual block devices
+ */
+
+#include <xeno/config.h>
+#include <xeno/types.h>
+#include <xeno/lib.h>
+#include <asm/io.h>
+#include <xeno/slab.h>
+#include <xeno/sched.h>
+#include <xeno/vbd.h>
+#include <xeno/blkdev.h>
+#include <xeno/keyhandler.h>
+#include <asm/current.h>
+#include <asm/domain_page.h>
+
+/* Global list of all possible vbds. This can be changed in
+ the following way:
+
+ 1) UNUSED vbd -> RO or RW vbd. This requires the spinlock.
+
+ 2) RO or RW -> UNUSED. This requires the lock and can only happen
+ during process teardown.
+
+ This means that processes can access entries in the list safely
+ without having to hold any lock at all: they already have an entry
+ allocated, and we know that entry can't become unused, as vbds
+ are only torn down when the domain is dieing, by which point it
+ can't be accessing them anymore. */
+static vbd_t xvbds[XEN_MAX_VBDS];
+static spinlock_t xvbd_lock = SPIN_LOCK_UNLOCKED;
+
+#if 0
+#define DPRINTK(_f, _a...) printk( _f , ## _a )
+#else
+#define DPRINTK(_f, _a...) ((void)0)
+#endif
+
+/*
+ * xen_vbd_map_request
+ *
+ * xen_device must be a valid device.
+ *
+ * NB. All offsets and sizes here are in sector units.
+ * eg. 'size == 1' means an actual size of 512 bytes.
+ *
+ * Note that no locking is performed here whatsoever --
+ * we rely on the fact that once vbd information is
+ * established, it is only modified by domain shutdown,
+ * and so if this is being called, noone is trying
+ * to modify the vbd list.
+ */
+int xen_vbd_map_request(
+ phys_seg_t *pseg, struct task_struct *p, int operation,
+ unsigned short vbd_number,
+ unsigned long sect_nr, unsigned long buffer, unsigned short nr_sects)
+{
+ vbd_t *seg;
+ extent_t *ext;
+ int sum, i;
+
+ vbd_number &= XENDEV_IDX_MASK;
+ if ( vbd_number >= XEN_MAX_VBDS )
+ {
+ DPRINTK("invalid vbd number. %d %d\n",
+ vbd_number, XEN_MAX_VBDS);
+ goto fail;
+ }
+
+ seg = p->vbd_list[vbd_number];
+ if ( seg == NULL )
+ {
+ DPRINTK("vbd is null. %d\n", vbd_number);
+ goto fail;
+ }
+
+ /* check domain permissions */
+ if ( seg->domain != p->domain )
+ {
+ DPRINTK("seg is for another domain. %d %d\n", seg->domain, p->domain);
+ goto fail;
+ }
+
+ /* check rw access */
+ if ( ((operation == WRITE) && (seg->mode != XEN_VBD_RW)) ||
+ ((operation == READ) && (seg->mode == XEN_VBD_UNUSED)) )
+ {
+ DPRINTK("illegal operation: %d %d\n", operation, seg->mode);
+ goto fail;
+ }
+
+ if ( (nr_sects + sect_nr) <= sect_nr )
+ {
+ DPRINTK("sector + size wrap! %08lx %04x\n", sect_nr, nr_sects);
+ goto fail;
+ }
+
+ /* find extent, check size */
+ sum = 0;
+ i = 0;
+ ext = seg->extents;
+ while ( (i < seg->num_extents) && ((sum + ext->nr_sectors) <= sect_nr) )
+ {
+ sum += ext->nr_sectors;
+ ext++; i++;
+ }
+
+ if ( (sum + ext->nr_sectors) <= sect_nr )
+ {
+ DPRINTK("extent size mismatch: %d %d : %d %ld %ld\n",
+ i, seg->num_extents, sum, ext->nr_sectors, sect_nr);
+ goto fail;
+ }
+
+ pseg->sector_number = (sect_nr - sum) + ext->start_sector;
+ pseg->buffer = buffer;
+ pseg->nr_sects = nr_sects;
+ pseg->dev = xendev_to_physdev(ext->raw_device);
+ if ( pseg->dev == 0 )
+ {
+ DPRINTK ("invalid device 0x%x 0x%lx 0x%lx\n",
+ ext->raw_device, ext->start_sector, ext->nr_sectors);
+ goto fail;
+ }
+
+ /* We're finished if the virtual extent didn't overrun the phys extent. */
+ if ( (sum + ext->nr_sectors) >= (sect_nr + nr_sects) )
+ return 1; /* entire read fits in this extent */
+
+ /* Hmmm... make sure there's another extent to overrun onto! */
+ if ( (i+1) == seg->num_extents )
+ {
+ DPRINTK ("not enough extents %d %d\n",
+ i, seg->num_extents);
+ goto fail;
+ }
+
+ pseg[1].nr_sects = (sect_nr + nr_sects) - (sum + ext->nr_sectors);
+ pseg[0].nr_sects = sum + ext->nr_sectors - sect_nr;
+ pseg[1].buffer = buffer + (pseg->nr_sects << 9);
+ pseg[1].sector_number = ext[1].start_sector;
+ pseg[1].dev = xendev_to_physdev(ext[1].raw_device);
+ if ( pseg[1].dev == 0 )
+ {
+ DPRINTK ("bogus device for pseg[1] \n");
+ goto fail;
+ }
+
+ /* We don't allow overrun onto a third physical extent. */
+ if ( pseg[1].nr_sects > ext[1].nr_sectors )
+ {
+ DPRINTK ("third extent\n");
+ DPRINTK (" sum:%d, e0:%ld, e1:%ld p1.sect:%ld p1.nr:%d\n",
+ sum, ext[0].nr_sectors, ext[1].nr_sectors,
+ pseg[1].sector_number, pseg[1].nr_sects);
+ goto fail;
+ }
+
+ return 2; /* We overran onto a second physical extent. */
+
+ fail:
+ DPRINTK ("xen_vbd_map_request failure\n");
+ DPRINTK ("operation: %d\n", operation);
+ DPRINTK ("vbd number: %d\n", vbd_number);
+ DPRINTK ("sect_nr: %ld 0x%lx\n", sect_nr, sect_nr);
+ DPRINTK ("nr_sects: %d 0x%x\n", nr_sects, nr_sects);
+ return -1;
+}
+
+/*
+ * vbd_probe_devices:
+ *
+ * add the virtual block devices for this domain to a xen_disk_info_t;
+ * we assume xdi->count points to the first unused place in the array.
+ */
+void vbd_probe_devices(xen_disk_info_t *xdi, struct task_struct *p)
+{
+ int loop, i;
+ unsigned long capacity = 0, device;
+
+ spin_lock(&xvbd_lock);
+ for (loop = 0; loop < XEN_MAX_VBDS; loop++ )
+ {
+ if ( (xvbds[loop].mode == XEN_VBD_UNUSED) ||
+ (xvbds[loop].domain != p->domain) )
+ continue;
+
+ device = MK_VIRTUAL_XENDEV(xvbds[loop].vbd_number);
+ for ( i = 0; i < xvbds[loop].num_extents; i++ )
+ capacity += xvbds[loop].extents[i].nr_sectors;
+
+ xdi->disks[xdi->count].device = device;
+ xdi->disks[xdi->count].capacity = capacity;
+ xdi->count++;
+ }
+ spin_unlock(&xvbd_lock);
+ return;
+}
+
+/*
+ * xen_refresh_vbd_list
+ *
+ * find all vbds associated with a domain and assign
+ * them to the domain
+ *
+ */
+void xen_refresh_vbd_list (struct task_struct *p)
+{
+ int loop;
+
+ spin_lock(&xvbd_lock);
+ for (loop = 0; loop < XEN_MAX_VBDS; loop++)
+ {
+ if ( (xvbds[loop].mode == XEN_VBD_UNUSED) ||
+ (xvbds[loop].domain != p->domain) )
+ continue;
+
+ p->vbd_list[xvbds[loop].vbd_number] = &xvbds[loop];
+ }
+ spin_unlock(&xvbd_lock);
+}
+
+/*
+ * create a new vbd for a domain
+ *
+ * return 0 on success, 1 on failure
+ *
+ * if we see the same DOM#/SEG# combination, we reuse the slot in
+ * the vbd table (overwriting what was there before).
+ * an alternative would be to raise an error if the slot is reused.
+ */
+int xen_vbd_create(xv_disk_t *xvd_in)
+{
+ int idx;
+ int loop;
+ xv_disk_t *xvd = map_domain_mem(virt_to_phys(xvd_in));
+ struct task_struct *p;
+
+ spin_lock(&xvbd_lock);
+ for (idx = 0; idx < XEN_MAX_VBDS; idx++)
+ {
+ if (xvbds[idx].mode == XEN_VBD_UNUSED ||
+ (xvbds[idx].domain == xvd->domain &&
+ xvbds[idx].vbd_number == xvd->vbd)) break;
+ }
+ if (idx == XEN_MAX_VBDS)
+ {
+ printk (KERN_ALERT "xen_vbd_create: unable to find free slot\n");
+ unmap_domain_mem(xvd);
+ return 1;
+ }
+
+ xvbds[idx].mode = xvd->mode;
+ xvbds[idx].domain = xvd->domain;
+ xvbds[idx].vbd_number = xvd->vbd;
+ memcpy(xvbds[idx].key, xvd->key, XEN_VBD_KEYSIZE);
+ xvbds[idx].num_extents = xvd->ext_count;
+
+
+ if (xvbds[idx].extents)
+ kfree(xvbds[idx].extents);
+ xvbds[idx].extents = (extent_t *)kmalloc(
+ sizeof(extent_t)*xvd->ext_count,
+ GFP_KERNEL);
+
+ /* could memcpy, but this is safer */
+ for (loop = 0; loop < xvd->ext_count; loop++)
+ {
+ xvbds[idx].extents[loop].raw_device = xvd->extents[loop].disk;
+ xvbds[idx].extents[loop].start_sector =
+ xvd->extents[loop].offset;
+ xvbds[idx].extents[loop].nr_sectors = xvd->extents[loop].size;
+ if (xvbds[idx].extents[loop].nr_sectors == 0)
+ {
+ printk("xen_vbd_create: extent %d is zero length\n", loop);
+ unmap_domain_mem(xvd);
+ return 1;
+ }
+ }
+
+ /* if the domain exists, assign the vbd to the domain */
+ p = find_domain_by_id(xvd->domain);
+ if (p != NULL)
+ {
+ p->vbd_list[xvd->vbd] = &xvbds[idx];
+ put_task_struct(p);
+ }
+
+ spin_unlock(&xvbd_lock);
+
+ unmap_domain_mem(xvd);
+ return 0;
+}
+
+/*
+ * delete a vbd from a domain
+ *
+ * return 0 on success, 1 on failure
+ *
+ * This should *only* be called from domain shutdown, or else we
+ * race with access checking.
+ */
+int xen_vbd_delete(struct task_struct *p, int segnr)
+{
+ vbd_t *seg;
+
+ if (!p) {
+ printk("xen_vbd delete called with NULL domain?\n");
+ BUG();
+ return 1;
+ }
+
+ if (segnr < 0 || segnr > XEN_MAX_VBDS) {
+ printk("xen_vbd_delete called with bad segnr?\n");
+ BUG();
+ return 1;
+ }
+
+ if (!p->vbd_list[segnr])
+ return 1;
+
+ seg = p->vbd_list[segnr];
+
+ /* sanity checking */
+ if (seg->domain != p->domain || seg->vbd_number != segnr ||
+ (seg->mode != XEN_VBD_RO && seg->mode != XEN_VBD_RW) ||
+ seg->num_extents <= 0 || seg->extents == NULL) {
+ printk("vbd is insane!\n");
+ BUG();
+ return 1;
+ }
+
+ spin_lock(&xvbd_lock);
+
+ p->vbd_list[segnr] = NULL;
+ seg->domain = -1;
+ seg->vbd_number = -1;
+ kfree(seg->extents);
+ seg->mode = XEN_VBD_UNUSED;
+
+ spin_unlock(&xvbd_lock);
+
+ return 0;
+}
+
+static void dump_vbds(u_char key, void *dev_id, struct pt_regs *regs)
+{
+ int loop, i;
+ struct task_struct *p;
+
+ printk("vbd list\n");
+ for (loop = 0; loop < XEN_MAX_VBDS; loop++)
+ {
+ if (xvbds[loop].mode != XEN_VBD_UNUSED)
+ {
+ printk(" %2d: %s dom%d, seg# %d, num_exts: %d\n",
+ loop,
+ xvbds[loop].mode == XEN_VBD_RO ? "RO" : "RW",
+ xvbds[loop].domain, xvbds[loop].vbd_number,
+ xvbds[loop].num_extents);
+ for (i = 0; i < xvbds[loop].num_extents; i++)
+ {
+ printk(" extent %d: raw device 0x%x, start_sector 0x%lx"
+ " nr_sectors 0x%lx\n",
+ i, xvbds[loop].extents[i].raw_device,
+ xvbds[loop].extents[i].start_sector,
+ xvbds[loop].extents[i].nr_sectors);
+ }
+ }
+ }
+
+ printk("vbds by domain (index into vbds list)\n");
+ p = current;
+ do
+ {
+ if(is_idle_task(p))
+ continue;
+
+ printk(" domain %d: ", p->domain);
+ for (loop = 0; loop < XEN_MAX_VBDS; loop++)
+ {
+ if (p->vbd_list[loop])
+ {
+ printk (" %d", p->vbd_list[loop] - xvbds);
+ }
+ }
+ printk("\n");
+ p = p->next_task;
+ } while (p != current);
+}
+
+/*
+ * initialize vbds
+ */
+
+void xen_vbd_initialize(void)
+{
+ memset (xvbds, 0, sizeof(xvbds));
+
+ add_key_handler('S', dump_vbds, "dump vbds");
+}
+
+
+/* The idea is that, for each sector of each disk, each domain has two
+ bits, saying whether they can read the sector or write it. That
+ would take too much memory, so instead each process has a list of
+ (device, start, end, mode) quads which say what it has access to,
+ and we fake the logical view on top of that. */
+struct physdisk_ace {
+ struct list_head list;
+ unsigned short device;
+ unsigned short partition;
+ unsigned long start_sect;
+ unsigned long n_sectors;
+ int mode;
+};
+
+
+/* Operation is a blkdev constant i.e. READ, WRITE, ... */
+/* Must be called with p->physdev_lock held. */
+static struct physdisk_ace *find_ace(const struct task_struct *p,
+ unsigned short dev,
+ unsigned long sect, int operation)
+{
+ struct list_head *cur_ace_head;
+ struct physdisk_ace *cur_ace;
+
+ list_for_each(cur_ace_head, &p->physdisk_aces)
+ {
+ cur_ace = list_entry(cur_ace_head, struct physdisk_ace, list);
+ DPRINTK("Is [%lx, %lx) good for %lx?\n",
+ cur_ace->start_sect,
+ cur_ace->start_sect + cur_ace->n_sectors, sect);
+ if ( (sect >= cur_ace->start_sect) &&
+ (sect < (cur_ace->start_sect + cur_ace->n_sectors)) &&
+ (dev == cur_ace->device) &&
+ (((operation == READ) && (cur_ace->mode & PHYSDISK_MODE_R)) ||
+ ((operation == WRITE) && (cur_ace->mode & PHYSDISK_MODE_W))) )
+ return cur_ace;
+ }
+ return NULL;
+}
+
+/* Hold the lock on entry, it remains held on exit. */
+static void xen_physdisk_revoke_access(unsigned short dev,
+ unsigned long start_sect,
+ unsigned long n_sectors,
+ struct task_struct *p)
+{
+ /* Find every ace which intersects [start_sect, start_sect +
+ n_sectors] and either remove it completely or truncate it
+ down. */
+ struct list_head *cur_ace_head;
+ struct physdisk_ace *cur_ace, *new_ace;
+ unsigned long kill_zone_end, ace_end;
+
+ kill_zone_end = start_sect + n_sectors;
+ list_for_each(cur_ace_head, &p->physdisk_aces)
+ {
+ cur_ace = list_entry(cur_ace_head, struct physdisk_ace, list);
+ ace_end = cur_ace->start_sect + cur_ace->n_sectors;
+ if ( (cur_ace->start_sect >= kill_zone_end) ||
+ (ace_end <= start_sect) ||
+ (cur_ace->device != dev) )
+ continue;
+
+ DPRINTK("Killing ace [%lx, %lx) against kill zone [%lx, %lx)\n",
+ cur_ace->start_sect, ace_end, start_sect, kill_zone_end);
+
+ if ( (cur_ace->start_sect >= start_sect) &&
+ (ace_end <= kill_zone_end) )
+ {
+ /* ace entirely within kill zone -> kill it */
+ list_del(cur_ace_head);
+ cur_ace_head = cur_ace_head->prev;
+ kfree(cur_ace);
+ }
+ else if ( ace_end <= kill_zone_end )
+ {
+ /* ace start before kill start, ace end in kill zone,
+ move ace end. */
+ cur_ace->n_sectors = start_sect - cur_ace->start_sect;
+ }
+ else if ( cur_ace->start_sect >= start_sect )
+ {
+ /* ace start after kill start, ace end outside kill zone,
+ move ace start. */
+ cur_ace->start_sect = kill_zone_end;
+ cur_ace->n_sectors = ace_end - cur_ace->start_sect;
+ }
+ else
+ {
+ /* The fun one: the ace entirely includes the kill zone. */
+ /* Cut the current ace down to just the bit before the kzone,
+ create a new ace for the bit just after it. */
+ new_ace = kmalloc(sizeof(*cur_ace), GFP_KERNEL);
+ new_ace->device = dev;
+ new_ace->start_sect = kill_zone_end;
+ new_ace->n_sectors = ace_end - kill_zone_end;
+ new_ace->mode = cur_ace->mode;
+
+ cur_ace->n_sectors = start_sect - cur_ace->start_sect;
+
+ list_add(&new_ace->list, cur_ace_head);
+ }
+ }
+}
+
+/* Hold the lock on entry, it remains held on exit. */
+static int xen_physdisk_grant_access(unsigned short dev,
+ unsigned short partition,
+ unsigned long start_sect,
+ unsigned long n_sectors,
+ int mode, struct task_struct *p)
+{
+ struct physdisk_ace *cur_ace;
+
+ /* Make sure it won't overlap with any existing ACEs. */
+ /* XXX this isn't quite right if the domain already has read access
+ and we try to grant write access, or vice versa. */
+ xen_physdisk_revoke_access(dev, start_sect, n_sectors, p);
+
+ if ( mode )
+ {
+ cur_ace = kmalloc(sizeof(*cur_ace), GFP_KERNEL);
+ cur_ace->device = dev;
+ cur_ace->start_sect = start_sect;
+ cur_ace->n_sectors = n_sectors;
+ cur_ace->mode = mode;
+ cur_ace->partition = partition;
+
+ list_add_tail(&cur_ace->list, &p->physdisk_aces);
+ }
+
+ return 0;
+}
+
+static void xen_physdisk_probe_access(physdisk_probebuf_t * buf,
+ struct task_struct *p)
+{
+ int n_aces;
+ struct list_head *cur_ace_head;
+ struct physdisk_ace *cur_ace;
+ int x = 0;
+
+ n_aces = 0;
+ list_for_each(cur_ace_head, &p->physdisk_aces)
+ {
+ x++;
+ if ( x >= buf->start_ind )
+ {
+ cur_ace = list_entry(cur_ace_head, struct physdisk_ace, list);
+ buf->entries[n_aces].device = cur_ace->device;
+ buf->entries[n_aces].partition = cur_ace->partition;
+ buf->entries[n_aces].start_sect = cur_ace->start_sect;
+ buf->entries[n_aces].n_sectors = cur_ace->n_sectors;
+ buf->entries[n_aces].mode = cur_ace->mode;
+ n_aces++;
+ }
+ }
+ buf->n_aces = n_aces;
+}
+
+int xen_physdisk_grant(xp_disk_t * xpd_in)
+{
+ struct task_struct *p = current;
+ xp_disk_t *xpd = map_domain_mem(virt_to_phys(xpd_in));
+ int res;
+
+ p = find_domain_by_id(xpd->domain);
+ if ( p == NULL )
+ {
+ DPRINTK("Bad domain!\n");
+ res = 1;
+ goto out;
+ }
+
+ spin_lock(&p->physdev_lock);
+ res = xen_physdisk_grant_access(xpd->device,
+ xpd->partition,
+ xpd->start_sect,
+ xpd->n_sectors, xpd->mode, p);
+ spin_unlock(&p->physdev_lock);
+ put_task_struct(p);
+
+ out:
+ unmap_domain_mem(xpd);
+ return res;
+}
+
+int xen_physdisk_probe(struct task_struct *requesting_domain,
+ physdisk_probebuf_t * buf_in)
+{
+ struct task_struct *p;
+ physdisk_probebuf_t *buf = map_domain_mem(virt_to_phys(buf_in));
+ int res;
+
+ if ( (requesting_domain->domain != 0) &&
+ (requesting_domain->domain != buf->domain) )
+ {
+ res = 1;
+ goto out;
+ }
+
+ p = find_domain_by_id(buf->domain);
+ if ( p == NULL )
+ {
+ res = 1;
+ goto out;
+ }
+
+ spin_lock(&p->physdev_lock);
+ xen_physdisk_probe_access(buf, p);
+ spin_unlock(&p->physdev_lock);
+ put_task_struct(p);
+
+ res = 0;
+ out:
+ unmap_domain_mem(buf);
+ return res;
+}
+
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+
+int xen_physdisk_access_okay(phys_seg_t * pseg, struct task_struct *p,
+ int operation)
+{
+ struct physdisk_ace *cur_ace;
+ unsigned long sect;
+
+ DPRINTK
+ ("Checking access for domain %d, start sect 0x%lx, length 0x%x.\n",
+ p->domain, pseg->sector_number, pseg->nr_sects);
+
+ for ( sect = pseg->sector_number;
+ sect < pseg->sector_number + pseg->nr_sects; )
+ {
+ /* XXX this would be a lot faster if the aces were sorted on start
+ address. Also in revoke_access. */
+ spin_lock(&p->physdev_lock);
+ cur_ace = find_ace(p, pseg->dev, sect, operation);
+ spin_unlock(&p->physdev_lock);
+ if ( cur_ace == NULL )
+ return 0;
+ sect +=
+ MAX(cur_ace->n_sectors,
+ pseg->nr_sects + pseg->sector_number - sect);
+ }
+ return 1;
+}
+
+void destroy_physdisk_aces(struct task_struct *p)
+{
+ struct list_head *cur_ace_head, *next_head;
+ struct physdisk_ace *cur_ace;
+
+ for ( cur_ace_head = p->physdisk_aces.next;
+ cur_ace_head != &p->physdisk_aces;
+ cur_ace_head = next_head )
+ {
+ cur_ace = list_entry(cur_ace_head, struct physdisk_ace, list);
+ next_head = cur_ace_head->next;
+ kfree(cur_ace);
+ }
+}
+
#include <xeno/types.h>
#include <xeno/lib.h>
#include <xeno/ide.h>
-#include <xeno/segment.h>
-#include <hypervisor-ifs/block.h>
+#include <xeno/vbd.h>
#include <asm/domain_page.h>
#include <asm/io.h>
{
int loop;
unsigned int unit;
- xen_disk_info_t *xen_xdi = map_domain_mem(virt_to_phys(xdi));
unsigned long capacity;
unsigned short device, type;
ide_drive_t *drive;
device = MK_IDE_XENDEV((loop * MAX_DRIVES) + unit);
capacity = current_capacity(drive);
- xen_xdi->disks[xen_xdi->count].device = device;
- xen_xdi->disks[xen_xdi->count].type = type;
- xen_xdi->disks[xen_xdi->count].capacity = capacity;
- xen_xdi->count++;
+ xdi->disks[xdi->count].device = device;
+ xdi->disks[xdi->count].type = type;
+ xdi->disks[xdi->count].capacity = capacity;
+ xdi->count++;
printk("Device %d: IDE-XENO (%s) capacity %ldkB (%ldMB)\n",
- xen_xdi->count, (type == XD_TYPE_DISK) ? "disk" :
+ xdi->count, (type == XD_TYPE_DISK) ? "disk" :
((type == XD_TYPE_CDROM) ? "cdrom" : "unknown"),
capacity>>1, capacity>>11);
}
}
-
- unmap_domain_mem(xen_xdi);
+
+ return;
}
/*
-** XXX SMH: gross 'probe' function to allow xeno world to grope us;
-** this should really not be in the disk-specific code as it should
-** report tapes, CDs, etc. But for now this looks like the easiest
-** place to hook it in :-(
+** scsi_probe_devices:
+**
+** add the scsi block devices for this domain to a xen_disk_info_t;
+** we assume xdi->count points to the first unused place in the array.
+**
+** XXX SMH: this is a rather gross 'probe' function to allow xeno world
+** to grope us; this should really not be in the disk-specific code as
+** it should report tapes, CDs, etc. But for now this looks like the
+** easiest place to hook it in :-(
+**
*/
void scsi_probe_devices(xen_disk_info_t *xdi)
{
Scsi_Disk *sd;
int i;
- xen_disk_info_t *xen_xdi = map_domain_mem(virt_to_phys(xdi));
unsigned long capacity, device;
for ( sd = rscsi_disks, i = 0; i < sd_template.dev_max; i++, sd++ )
capacity = sd->capacity;
/* XXX SMH: if make generic, need to properly determine 'type' */
- xen_xdi->disks[xen_xdi->count].device = device;
- xen_xdi->disks[xen_xdi->count].type = XD_TYPE_DISK;
- xen_xdi->disks[xen_xdi->count].capacity = capacity;
- xen_xdi->count++;
+ xdi->disks[xdi->count].device = device;
+ xdi->disks[xdi->count].type = XD_TYPE_DISK;
+ xdi->disks[xdi->count].capacity = capacity;
+ xdi->count++;
printk("Device %d: SCSI-XENO (disk) capacity %ldkB (%ldMB)\n",
- xen_xdi->count, capacity>>1, capacity>>11);
+ xdi->count, capacity>>1, capacity>>11);
}
- unmap_domain_mem(xen_xdi);
+ return;
}
#define XEN_BLOCK_WRITE 1
#define XEN_BLOCK_READA 2
#define XEN_BLOCK_SPECIAL 4
-#define XEN_BLOCK_PROBE_BLK 5 /* get xhd config from hypervisor */
-#define XEN_BLOCK_DEBUG 6 /* debug */
-#define XEN_BLOCK_SEG_CREATE 7 /* create segment (vhd) */
-#define XEN_BLOCK_SEG_DELETE 8 /* delete segment (vhd) */
-#define XEN_BLOCK_PROBE_SEG 9 /* get vhd config from hypervisor */
+#define XEN_BLOCK_PROBE 5 /* get config from hypervisor */
+#define XEN_BLOCK_DEBUG 6 /* debug */
+#define XEN_BLOCK_VBD_CREATE 7 /* create vbd */
+#define XEN_BLOCK_VBD_DELETE 8 /* delete vbd */
+ /* XXX SMH: was 'probe vbd' */
#define XEN_BLOCK_PHYSDEV_GRANT 10 /* grant access to range of disk blocks */
-#define XEN_BLOCK_PHYSDEV_PROBE 11 /* probe for a domain's physdev
- accesses */
-#define XEN_BLOCK_PROBE_SEG_ALL 12 /* prove for every domain's segments,
- not just ours. */
+#define XEN_BLOCK_PHYSDEV_PROBE 11 /* probe for a domain's physdev accesses */
+ /* XXX SMH: was 'probe vbd all' */
/* NB. Ring size must be small enough for sizeof(blk_ring_t) <= PAGE_SIZE. */
#define BLK_RING_SIZE 64
xen_disk_t disks[XEN_MAX_DISK_COUNT];
} xen_disk_info_t;
-/*
- *
- * virtual disk (vhd) structures, used by XEN_BLOCK_SEG_{CREATE, DELETE}
- *
- */
-
-#define XEN_DISK_READ_WRITE 1
-#define XEN_DISK_READ_ONLY 2
-
-typedef struct xv_extent
-{
- int disk; /* physical disk number */
- unsigned long offset; /* offset in blocks into physical disk */
- unsigned long size; /* size in blocks */
-} xv_extent_t;
-
-#define XEN_SEGMENT_KEYSIZE 10
-
-typedef struct xv_disk
-{
- int mode; /* XEN_DISK_READ_WRITE or XEN_DISK_READ_ONLY */
- int domain; /* domain */
- int segment; /* segment number */
- char key[XEN_SEGMENT_KEYSIZE]; /* key for benefit of dom0 userspace */
- int ext_count; /* number of xv_extent_t to follow */
- xv_extent_t extents[XEN_MAX_DISK_COUNT]; /* arbitrary reuse of constant */
-} xv_disk_t;
-
-#define PHYSDISK_MODE_R 1
-#define PHYSDISK_MODE_W 2
-typedef struct xp_disk
-{
- int mode; /* 0 -> revoke existing access, otherwise bitmask of
- PHYSDISK_MODE_? constants */
- int domain;
- unsigned short device; /* XENDEV_??? + idx */
- unsigned short partition; /* partition number */
- unsigned long start_sect;
- unsigned long n_sectors;
-} xp_disk_t;
-
-#define PHYSDISK_MAX_ACES_PER_REQUEST 254 /* Make it fit in one page */
-typedef struct {
- int n_aces;
- int domain;
- int start_ind;
- struct {
- unsigned short device; /* XENDEV_??? + idx */
- unsigned short partition; /* partition number */
- unsigned long start_sect;
- unsigned long n_sectors;
- unsigned mode;
- } entries[PHYSDISK_MAX_ACES_PER_REQUEST];
-} physdisk_probebuf_t;
-
#endif
+++ /dev/null
-#ifndef __HYP_IFS_SEGMENT_H__
-#define __HYP_IFS_SEGMENT_H__
-
-#define XEN_MAX_SEGMENTS 100 /* total number of segments across all doms */
-
-#define XEN_SEGMENT_UNUSED 0 /* bzero default */
-#define XEN_SEGMENT_RO XEN_DISK_READ_ONLY
-#define XEN_SEGMENT_RW XEN_DISK_READ_WRITE
-
-typedef struct xen_segment_info
-{
- int count;
- struct {
- unsigned domain;
- unsigned seg_nr;
- char key[XEN_SEGMENT_KEYSIZE];
- unsigned short mode; /* UNUSED, RO, or RW. */
- } segments[XEN_MAX_SEGMENTS];
-} xen_segment_info_t;
-
-#endif /* __HYP_IFS_SEGMENT_H__ */
--- /dev/null
+#ifndef __HYP_IFS_VBD_H__
+#define __HYP_IFS_VBD_H__
+
+#define XEN_MAX_VBDS 100 /* total number of vbds across all doms */
+
+#define XEN_VBD_UNUSED 0 /* bzero default */
+#define XEN_DISK_READ_WRITE 1
+#define XEN_DISK_READ_ONLY 2
+#define XEN_VBD_RO XEN_DISK_READ_ONLY
+#define XEN_VBD_RW XEN_DISK_READ_WRITE
+
+/*
+ *
+ * virtual disk (vhd) structures, used by XEN_BLOCK_VBD_{CREATE, DELETE}
+ *
+ */
+
+typedef struct xv_extent
+{
+ int disk; /* physical disk number */
+ unsigned long offset; /* offset in blocks into physical disk */
+ unsigned long size; /* size in blocks */
+} xv_extent_t;
+
+#define XEN_VBD_KEYSIZE 10
+
+typedef struct xv_disk
+{
+ int mode; /* XEN_DISK_READ_WRITE or XEN_DISK_READ_ONLY */
+ int domain; /* domain */
+ int vbd; /* segment number */
+ char key[XEN_VBD_KEYSIZE]; /* key for benefit of dom0 userspace */
+ int ext_count; /* number of xv_extent_t to follow */
+ xv_extent_t extents[XEN_MAX_DISK_COUNT]; /* arbitrary reuse of constant */
+} xv_disk_t;
+
+#define PHYSDISK_MODE_R 1
+#define PHYSDISK_MODE_W 2
+typedef struct xp_disk
+{
+ int mode; /* 0 -> revoke existing access, otherwise bitmask of
+ PHYSDISK_MODE_? constants */
+ int domain;
+ unsigned short device; /* XENDEV_??? + idx */
+ unsigned short partition; /* partition number */
+ unsigned long start_sect;
+ unsigned long n_sectors;
+} xp_disk_t;
+
+#define PHYSDISK_MAX_ACES_PER_REQUEST 254 /* Make it fit in one page */
+typedef struct {
+ int n_aces;
+ int domain;
+ int start_ind;
+ struct {
+ unsigned short device; /* XENDEV_??? + idx */
+ unsigned short partition; /* partition number */
+ unsigned long start_sect;
+ unsigned long n_sectors;
+ unsigned mode;
+ } entries[PHYSDISK_MAX_ACES_PER_REQUEST];
+} physdisk_probebuf_t;
+
+
+typedef struct xen_vbd_info
+{
+ int count;
+ struct {
+ unsigned domain;
+ unsigned seg_nr;
+ char key[XEN_VBD_KEYSIZE];
+ unsigned short mode; /* UNUSED, RO, or RW. */
+ } vbds[XEN_MAX_VBDS];
+} xen_vbd_info_t;
+
+
+
+/* Block I/O trap operations and associated structures.
+ */
+
+#define BLOCK_IO_OP_SIGNAL 0 // let xen know we have work to do
+#define BLOCK_IO_OP_ATTACH_VBD 1 // attach a VBD to a given domain
+
+
+typedef struct _extent {
+ u16 raw_device;
+ ulong start_sector;
+ ulong nr_sectors;
+} extent_t;
+
+
+typedef struct _vbd_attach {
+ int domain;
+ u16 mode; // read-only or read-write
+ u16 device; // how this domain refers to this VBD
+ int nr_extents; // number of extents in the VBD
+ extent_t *extents; // pointer to /array/ of extents
+} vbd_attach_t;
+
+
+typedef struct block_io_op_st
+{
+ unsigned long cmd;
+ union
+ {
+ long signal_val_unused;
+ vbd_attach_t attach_info;
+ }
+ u;
+} block_io_op_t;
+
+
+
+
+#endif /* __HYP_IFS_VBD_H__ */
+++ /dev/null
-/* block.h
- *
- * this is the hypervisor end of the block io code.
- */
-
-#include <hypervisor-ifs/block.h>
-
-/* vif prototypes */
-blk_ring_t *create_block_ring(int domain);
-void destroy_block_ring(struct task_struct *p);
-
+++ /dev/null
-#ifndef PHYSDISK_ACES__
-#define PHYSDISK_ACES__
-
-struct task_struct;
-
-void destroy_physdisk_aces(struct task_struct *p);
-
-int xen_physdisk_grant(xp_disk_t *);
-int xen_physdisk_probe(struct task_struct *requesting_task,
- physdisk_probebuf_t *);
-int xen_physdisk_access_okay(phys_seg_t *pseg, struct task_struct *p,
- int operation);
-
-#endif /* PHYSDISK_ACES__ */
#define PF_CONSTRUCTED 0x8 /* Has the guest OS been fully built yet? */
#include <xeno/vif.h>
-#include <xeno/block.h>
-#include <xeno/segment.h>
+#include <xeno/vbd.h>
/* SMH: replace below when have explicit 'priv' flag or bitmask */
#define IS_PRIV(_p) ((_p)->domain == 0)
the process can do raw access
to. */
spinlock_t physdev_lock;
- segment_t *segment_list[XEN_MAX_SEGMENTS]; /* xvd */
+ vbd_t *vbd_list[XEN_MAX_VBDS]; /* vbds for this domain */
/* VM */
struct mm_struct mm;
+++ /dev/null
-#ifndef __SEGMENT_H__
-#define __SEGMENT_H__
-
-#include <hypervisor-ifs/block.h>
-#include <hypervisor-ifs/segment.h>
-
-/* Describes a physical disk extent. */
-typedef struct {
- unsigned short dev;
- unsigned short nr_sects;
- unsigned long sector_number;
- unsigned long buffer;
-} phys_seg_t;
-
-struct task_struct;
-
-void xen_segment_initialize(void);
-void xen_refresh_segment_list (struct task_struct *p);
-int xen_segment_create(xv_disk_t *xvd);
-int xen_segment_delete(struct task_struct *p, int segnr);
-int xen_segment_map_request(
- phys_seg_t *pseg, struct task_struct *p, int operation,
- unsigned short segment_number,
- unsigned long sect_nr, unsigned long buffer, unsigned short nr_sects);
-
-/*
- * virtual hard disks
- *
- * each segment is composed of a number of extents
- */
-
-typedef struct extent
-{
- int disk; /* A XEN_IDE_DEV or a XEN_SCSI_DEV */
- unsigned long offset; /* offset into disk */
- unsigned long size; /* size of this extent */
-} extent_t;
-
-typedef struct segment
-{
- int mode; /* UNUSED, RO, or RW */
- int domain;
- int segment_number; /* segment number for domain */
- char key[XEN_SEGMENT_KEYSIZE]; /* for the userspace tools in dom0 */
- int num_extents; /* number of extents */
- extent_t *extents;
-} segment_t;
-
-#endif
--- /dev/null
+/*
+** include/xeno/vbd.h:
+** -- xen internal declarations + prototypes for virtual block devices
+**
+*/
+#ifndef __VBD_H__
+#define __VBD_H__
+
+#include <hypervisor-ifs/block.h>
+#include <hypervisor-ifs/vbd.h>
+
+/* Describes a physical disk extent. */
+typedef struct {
+ unsigned short dev;
+ unsigned short nr_sects;
+ unsigned long sector_number;
+ unsigned long buffer;
+} phys_seg_t;
+
+struct task_struct;
+
+void xen_vbd_initialize(void);
+void xen_refresh_vbd_list (struct task_struct *p);
+int xen_vbd_create(xv_disk_t *xvd);
+int xen_vbd_delete(struct task_struct *p, int segnr);
+int xen_vbd_map_request(
+ phys_seg_t *pseg, struct task_struct *p, int operation,
+ unsigned short vbd_number,
+ unsigned long sect_nr, unsigned long buffer, unsigned short nr_sects);
+
+typedef struct vbd
+{
+ int mode; /* UNUSED, RO, or RW */
+ int domain;
+ int vbd_number; /* vbd number for domain */
+ char key[XEN_VBD_KEYSIZE]; /* for the userspace tools in dom0 */
+ int num_extents; /* number of extents */
+ extent_t *extents;
+} vbd_t;
+
+#endif
+
+#ifndef PHYSDISK_ACES__
+#define PHYSDISK_ACES__
+
+struct task_struct;
+
+void destroy_physdisk_aces(struct task_struct *p);
+
+int xen_physdisk_grant(xp_disk_t *);
+int xen_physdisk_probe(struct task_struct *requesting_task,
+ physdisk_probebuf_t *);
+int xen_physdisk_access_okay(phys_seg_t *pseg, struct task_struct *p,
+ int operation);
+
+#endif /* PHYSDISK_ACES__ */
O_TARGET := blk.o
-obj-y := xl_block.o xl_ide.o xl_scsi.o xl_segment.o xl_segment_proc.o info.o
+obj-y := xl_block.o xl_ide.o xl_scsi.o xl_vbd.o info.o
include $(TOPDIR)/Rules.make
static inline void signal_requests_to_xen(void)
{
+ block_io_op_t op;
+
DISABLE_SCATTERGATHER();
blk_ring->req_prod = req_prod;
- HYPERVISOR_block_io_op();
+
+ op.cmd = BLOCK_IO_OP_SIGNAL;
+ HYPERVISOR_block_io_op(&op);
+ return;
}
break;
case XLVIRT_MAJOR:
- gd = xlsegment_gendisk;
+ gd = xlvbd_gendisk;
break;
}
case XLVIRT_MAJOR:
DPRINTK_IOCTL(" BLKSSZGET: %x 0x%x\n", BLKSSZGET,
- xlsegment_hwsect(MINOR(dev)));
- return xlsegment_hwsect(MINOR(dev));
+ xlsbd_hwsect(MINOR(dev)));
+ return xlvbd_hwsect(MINOR(dev));
default:
printk(KERN_ALERT "BLKSSZGET ioctl() on bogus disk!\n");
if ( xdi != NULL )
{
memset(xdi, 0, sizeof(*xdi));
- xenolinux_control_msg(XEN_BLOCK_PROBE_SEG,
+ xenolinux_control_msg(XEN_BLOCK_PROBE,
(char *)xdi, sizeof(*xdi));
for ( i = 0; i < xdi->count; i++ )
if ( IS_VIRTUAL_XENDEV(xdi->disks[i].device) &&
* request block io
*
* id: for guest use only.
- * operation: XEN_BLOCK_{READ,WRITE,PROBE*,SEG*}
+ * operation: XEN_BLOCK_{READ,WRITE,PROBE,VBD*}
* buffer: buffer to read/write into. this should be a
* virtual address in the guest os.
*/
switch ( operation )
{
- case XEN_BLOCK_SEG_CREATE:
- case XEN_BLOCK_SEG_DELETE:
+ case XEN_BLOCK_VBD_CREATE:
+ case XEN_BLOCK_VBD_DELETE:
case XEN_BLOCK_PHYSDEV_GRANT:
case XEN_BLOCK_PHYSDEV_PROBE:
- case XEN_BLOCK_PROBE_BLK:
- case XEN_BLOCK_PROBE_SEG:
- case XEN_BLOCK_PROBE_SEG_ALL:
+ case XEN_BLOCK_PROBE:
if ( RING_FULL ) return 1;
phys_device = (kdev_t) 0;
sector_number = 0;
}
break;
- case XEN_BLOCK_SEG_CREATE:
- case XEN_BLOCK_SEG_DELETE:
- case XEN_BLOCK_PROBE_SEG:
- case XEN_BLOCK_PROBE_SEG_ALL:
- case XEN_BLOCK_PROBE_BLK:
+ case XEN_BLOCK_VBD_CREATE:
+ case XEN_BLOCK_VBD_DELETE:
+ case XEN_BLOCK_PROBE:
case XEN_BLOCK_PHYSDEV_GRANT:
case XEN_BLOCK_PHYSDEV_PROBE:
xlblk_control_msg_pending = bret->status;
int __init xlblk_init(void)
{
- int error;
+ int error;
xlblk_control_msg_pending = 0;
nr_pending = 0;
/* Probe for disk information. */
memset(&xlblk_disk_info, 0, sizeof(xlblk_disk_info));
- error = xenolinux_control_msg(XEN_BLOCK_PROBE_BLK,
+ error = xenolinux_control_msg(XEN_BLOCK_PROBE,
(char *)&xlblk_disk_info,
sizeof(xen_disk_info_t));
if ( error )
goto fail;
}
+ {
+ int i;
+ printk(KERN_ALERT "xlblk_init: xen returned info for %d disks\n",
+ xlblk_disk_info.count);
+ for(i=0; i < xlblk_disk_info.count; i++) {
+ printk("%d -- device no=%x, type=%d, capacity=%ldMB\n",
+ i, xlblk_disk_info.disks[i].device,
+ xlblk_disk_info.disks[i].type,
+ xlblk_disk_info.disks[i].capacity >> 11);
+
+ }
+
+ }
/* Pass the information to our fake IDE and SCSI susbystems. */
xlide_init(&xlblk_disk_info);
xlscsi_init(&xlblk_disk_info);
+ /* And do the same for the 'virtual block device' world */
+ xlvbd_init(&xlblk_disk_info);
+
return 0;
fail:
static void __exit xlblk_cleanup(void)
{
- xlide_cleanup();
+ xlvbd_cleanup();
xlscsi_cleanup();
+ xlide_cleanup();
free_irq(XLBLK_RESPONSE_IRQ, NULL);
}
#include <linux/blkdev.h>
#include <linux/major.h>
-#include <asm/hypervisor-ifs/block.h>
#include <asm/hypervisor-ifs/hypervisor-if.h>
+#include <asm/hypervisor-ifs/vbd.h>
#include <asm/io.h>
#include <asm/atomic.h>
#include <asm/uaccess.h>
extern struct gendisk *xlscsi_gendisk;
/* Virtual block-device subsystem. */
-extern int xlsegment_hwsect(int minor);
-extern struct gendisk *xlsegment_gendisk;
+extern int xlvbd_init(xen_disk_info_t *xdi);
+extern int xlvbd_hwsect(int minor);
+extern void xlvbd_cleanup(void);
+extern struct gendisk *xlvbd_gendisk;
extern unsigned short xldev_to_physdev(kdev_t xldev);
extern kdev_t physdev_to_xldev(unsigned short physdev);
+++ /dev/null
-/******************************************************************************
- * xl_segment.c
- *
- * Xenolinux virtual block-device driver (xvd).
- *
- */
-
-#include "xl_block.h"
-
-#define MAJOR_NR XLVIRT_MAJOR
-#include <linux/blk.h>
-
-/* Copied from linux/ide.h */
-typedef unsigned char byte;
-
-#define XLVIRT_MAX 256
-#define XLVIRT_MAJOR_NAME "xvd"
-static int xlseg_blksize_size[XLVIRT_MAX];
-static int xlseg_hardsect_size[XLVIRT_MAX];
-static int xlseg_max_sectors[XLVIRT_MAX];
-
-struct gendisk *xlsegment_gendisk = NULL;
-
-static xen_disk_info_t xlseg_disk_info;
-
-static struct block_device_operations xlsegment_block_fops =
-{
- open: xenolinux_block_open,
- release: xenolinux_block_release,
- ioctl: xenolinux_block_ioctl,
- check_media_change: xenolinux_block_check,
- revalidate: xenolinux_block_revalidate,
-};
-
-
-int xlsegment_hwsect(int minor)
-{
- return xlseg_hardsect_size[minor];
-}
-
-
-int __init xlseg_init(void)
-{
- int i, result, units, minors, disk;
- xen_disk_info_t *xdi = &xlseg_disk_info;
- struct gendisk *gd;
-
- SET_MODULE_OWNER(&xlsegment_block_fops);
-
- /* Probe for disk information. */
- memset(xdi, 0, sizeof(*xdi));
- xenolinux_control_msg(XEN_BLOCK_PROBE_SEG, (char *)xdi, sizeof(*xdi));
-
- DPRINTK("xvd block device probe:\n");
- for ( i = 0; i < xdi->count; i++ )
- {
- DPRINTK(" %2d: device: %d, capacity: %ld\n",
- i, xdi->disks[i].device, xdi->disks[i].capacity);
- }
-
- result = register_blkdev(XLVIRT_MAJOR, XLVIRT_MAJOR_NAME,
- &xlsegment_block_fops);
- if ( result < 0 )
- {
- printk(KERN_ALERT "XL Segment: can't get major %d\n", XLVIRT_MAJOR);
- return result;
- }
-
- /* Initialize global arrays. */
- for (i = 0; i < XLVIRT_MAX; i++)
- {
- xlseg_blksize_size[i] = 512;
- xlseg_hardsect_size[i] = 512;
- xlseg_max_sectors[i] = 128;
- }
-
- blk_size[XLVIRT_MAJOR] = NULL;
- blksize_size[XLVIRT_MAJOR] = xlseg_blksize_size;
- hardsect_size[XLVIRT_MAJOR] = xlseg_hardsect_size;
- max_sectors[XLVIRT_MAJOR] = xlseg_max_sectors;
- read_ahead[XLVIRT_MAJOR] = 8;
-
- blk_init_queue(BLK_DEFAULT_QUEUE(XLVIRT_MAJOR), do_xlblk_request);
-
- /*
- * Turn off barking 'headactive' mode. We dequeue buffer heads as
- * soon as we pass them down to Xen.
- */
- blk_queue_headactive(BLK_DEFAULT_QUEUE(XLVIRT_MAJOR), 0);
-
- units = XLVIRT_MAX >> XLVIRT_PARTN_SHIFT;
-
- /* Construct an appropriate gendisk structure. */
- minors = units * (1<<XLVIRT_PARTN_SHIFT);
- gd = kmalloc(sizeof(struct gendisk), GFP_KERNEL);
- gd->sizes = kmalloc(minors * sizeof(int), GFP_KERNEL);
- gd->part = kmalloc(minors * sizeof(struct hd_struct), GFP_KERNEL);
- gd->major = XLVIRT_MAJOR;
- gd->major_name = XLVIRT_MAJOR_NAME;
- gd->minor_shift = XLVIRT_PARTN_SHIFT;
- gd->max_p = 1<<XLVIRT_PARTN_SHIFT;
- gd->nr_real = units;
- gd->real_devices = kmalloc(units * sizeof(xl_disk_t), GFP_KERNEL);
- gd->next = NULL;
- gd->fops = &xlsegment_block_fops;
- gd->de_arr = kmalloc(sizeof(*gd->de_arr) * units, GFP_KERNEL);
- gd->flags = kmalloc(sizeof(*gd->flags) * units, GFP_KERNEL);
- memset(gd->sizes, 0, minors * sizeof(int));
- memset(gd->part, 0, minors * sizeof(struct hd_struct));
- memset(gd->de_arr, 0, sizeof(*gd->de_arr) * units);
- memset(gd->flags, 0, sizeof(*gd->flags) * units);
- memset(gd->real_devices, 0, sizeof(xl_disk_t) * units);
- xlsegment_gendisk = gd;
- add_gendisk(gd);
-
- /* Now register each disk in turn. */
- for ( i = 0; i < xdi->count; i++ )
- {
- disk = xdi->disks[i].device & XENDEV_IDX_MASK;
-
- if ( !IS_VIRTUAL_XENDEV(xdi->disks[i].device) ||
- (disk >= XLVIRT_DEVS_PER_MAJOR) )
- continue;
-
- ((xl_disk_t *)gd->real_devices)[disk].capacity =
- xdi->disks[i].capacity;
- register_disk(gd,
- MKDEV(XLVIRT_MAJOR, disk<<XLVIRT_PARTN_SHIFT),
- 1<<XLVIRT_PARTN_SHIFT,
- &xlsegment_block_fops,
- xdi->disks[i].capacity);
- }
-
- printk(KERN_ALERT
- "XenoLinux Virtual Segment Device Driver installed [device: %d]\n",
- XLVIRT_MAJOR);
-
- return 0;
-}
-
-
-static void __exit xlseg_cleanup(void)
-{
- if ( xlsegment_gendisk == NULL ) return;
-
- blk_cleanup_queue(BLK_DEFAULT_QUEUE(XLVIRT_MAJOR));
-
- xlsegment_gendisk = NULL;
-
- read_ahead[XLVIRT_MAJOR] = 0;
-
- if ( blksize_size[XLVIRT_MAJOR] != NULL )
- {
- kfree(blksize_size[XLVIRT_MAJOR]);
- blksize_size[XLVIRT_MAJOR] = NULL;
- }
-
- if ( hardsect_size[XLVIRT_MAJOR] != NULL )
- {
- kfree(hardsect_size[XLVIRT_MAJOR]);
- hardsect_size[XLVIRT_MAJOR] = NULL;
- }
-
- if ( max_sectors[XLVIRT_MAJOR] != NULL )
- {
- kfree(max_sectors[XLVIRT_MAJOR]);
- max_sectors[XLVIRT_MAJOR] = NULL;
- }
-
- if ( unregister_blkdev(XLVIRT_MAJOR, XLVIRT_MAJOR_NAME) != 0 )
- {
- printk(KERN_ALERT
- "XenoLinux Virtual Segment Device Driver"
- " uninstalled w/ errs\n");
- }
-}
-
-
-#ifdef MODULE
-module_init(xlseg_init);
-module_exit(xlseg_cleanup);
-#endif
+++ /dev/null
-/*
- * xl_segment_proc.c
- *
- * XenoLinux virtual disk proc interface .
- */
-
-#include "xl_block.h"
-#include <asm/xeno_proc.h>
-#include <linux/delay.h>
-#include <linux/seq_file.h>
-#include <asm/hypervisor-ifs/segment.h>
-
-static struct proc_dir_entry *vhd;
-
-static void *proc_vhd_next(struct seq_file *s, void *v, loff_t *pos)
-{
- xen_segment_info_t *data;
-
- if ( pos != NULL )
- ++(*pos);
-
- data = v;
- return data->count-- ? NULL : v;
-}
-
-static void *proc_vhd_start(struct seq_file *s, loff_t *ppos)
-{
- loff_t pos = *ppos;
- xen_segment_info_t *data;
-
- data = kmalloc(sizeof(*data), GFP_KERNEL);
- xenolinux_control_msg(XEN_BLOCK_PROBE_SEG_ALL, (char *)data, sizeof(*data));
- data->count -= pos;
-
- if (data->count > 0)
- return data;
-
- kfree(data);
- return NULL;
-}
-
-static int proc_vhd_show(struct seq_file *s, void *v)
-{
- xen_segment_info_t *data = v;
-
- seq_printf (s,
- "%x %x %10.10s %x\n",
- data->segments[data->count - 1].domain,
- data->segments[data->count - 1].seg_nr,
- data->segments[data->count - 1].key,
- data->segments[data->count - 1].mode);
-
- return 0;
-}
-
-static void proc_vhd_stop(struct seq_file *s, void *v)
-{
- kfree(v);
-}
-
-static struct seq_operations proc_vhd_op = {
- .start = proc_vhd_start,
- .next = proc_vhd_next,
- .show = proc_vhd_show,
- .stop = proc_vhd_stop
-};
-
-static int proc_open_vhd(struct inode *inode, struct file *file)
-{
- return seq_open(file, &proc_vhd_op);
-}
-
-
-#define isdelim(c) \
- (c==' '||c==','||c=='\n'||c=='\r'||c=='\t'||c==':'||c=='('||c==')' ? 1 : 0)
-
-char *get_string(char *string) /* a bit like strtok */
-{
- static char *temp;
- int loop = 0;
-
- if (string != NULL)
- temp = string;
- else
- string = temp;
-
- try_again:
-
- while (!isdelim(string[loop]))
- {
- if (string[loop] == '\0')
- return NULL;
- loop++;
- }
-
- string[loop] = '\0';
- temp = (string + loop + 1);
-
- if (loop == 0)
- {
- string = temp;
- goto try_again;
- }
-
- return string;
-}
-
-
-#define isdigit(c) (c >= '0' && c <= '9' ? 1 : 0)
-unsigned long to_number(char *string) /* atoi */
-{
- unsigned long value = 0;
-
- if (string == NULL) return 0;
-
- while (!isdigit(*string) && *string != '\0') string++;
-
- while (isdigit(*string))
- {
- value = value * 10 + (*string - '0');
- string++;
- }
-
- return value;
-}
-
-static int proc_write_vhd(struct file *file, const char *buffer,
- size_t count, loff_t *offp)
-{
- char *local = kmalloc((count + 1) * sizeof(char), GFP_KERNEL);
- char *string;
- int loop;
- xv_disk_t xvd;
- int res;
-
- if( !(start_info.flags & SIF_PRIVILEGED) )
- return -EPERM;
-
- if (!local)
- return -ENOMEM;
-
- memset (&xvd, 0, sizeof(xvd));
-
- if (copy_from_user(local, buffer, count))
- {
- res = -EFAULT;
- goto out;
- }
- local[count] = '\0';
-
- res = count;
- string = get_string(local); /* domain specifier */
- if (string == NULL)
- {
- goto out;
- }
- if (*string != 'd' && *string != 'D')
- {
- printk (KERN_ALERT
- "error: domain specifier missing [%s]. should be \"domain\".\n",
- string);
- goto out;
- }
-
- string = get_string(NULL); /* domain number */
- if (string == NULL)
- {
- printk (KERN_ALERT "error: domain number missing\n");
- goto out;
- }
- xvd.domain = (int) to_number(string);
-
- string = get_string(NULL);
- if (string && (strcmp(string, "RO") == 0 || strcmp(string, "ro") == 0))
- {
- xvd.mode = XEN_DISK_READ_ONLY;
- }
- else if (string && (strcmp(string, "RW") == 0 || strcmp(string, "rw") == 0))
- {
- xvd.mode = XEN_DISK_READ_WRITE;
- }
- else
- {
- printk (KERN_ALERT
- "error: bad mode [%s]. should be \"rw\" or \"ro\".\n",
- string);
- goto out;
- }
-
- string = get_string(NULL); /* look for Segment */
- if (string == NULL || (*string != 's' && *string != 'S'))
- {
- printk (KERN_ALERT
- "error: segment specifier missing [%s]. should be \"segment\".\n",
- string);
- goto out;
- }
-
- string = get_string(NULL); /* segment number */
- if (string == NULL)
- {
- printk (KERN_ALERT "error: segment number missing\n");
- goto out;
- }
- xvd.segment = (int) to_number(string);
-
- string = get_string(NULL); /* look for key */
- if (string == NULL || (*string != 'k' && *string != 'K'))
- {
- printk (KERN_ALERT
- "error: key specifier missing [%s]. should be \"key\".\n",
- string);
- goto out;
- }
- string = get_string(NULL);
- if (string == NULL || strlen(string) != XEN_SEGMENT_KEYSIZE)
- {
- printk (KERN_ALERT "error: key missing\n");
- goto out;
- }
- memcpy(xvd.key, string, XEN_SEGMENT_KEYSIZE);
-
- string = get_string(NULL); /* look for Extents */
- if (string == NULL || (*string != 'e' && *string != 'E'))
- {
- printk (KERN_ALERT
- "error: extents specifier missing [%s]. should be \"extents\".\n",
- string);
- goto out;
- }
-
- string = get_string(NULL); /* number of extents */
- if (string == NULL)
- {
- printk (KERN_ALERT "error: number of extents missing\n");
- goto out;
- }
- xvd.ext_count = (int) to_number(string);
-
- /* ignore parenthesis */
-
- for (loop = 0; loop < xvd.ext_count; loop++)
- {
- string = get_string(NULL); /* look for Disk */
- if (string == NULL || (*string != 'd' && *string != 'D'))
- {
- printk (KERN_ALERT
- "hmm, extent disk specifier missing [%s]. should be \"disk\".\n",
- string);
- goto out;
- }
- string = get_string(NULL); /* disk number */
- if (string == NULL)
- {
- printk (KERN_ALERT "error: disk number missing\n");
- goto out;
- }
- xvd.extents[loop].disk = xldev_to_physdev((int) to_number(string));
-
- string = get_string(NULL); /* look for Offset */
- if (string == NULL || (*string != 'o' && *string != 'O'))
- {
- printk (KERN_ALERT
- "error: disk offset missing [%s]. should be \"offset\".\n",
- string);
- goto out;
- }
- string = get_string(NULL); /* offset */
- if (string == NULL)
- {
- printk (KERN_ALERT "error: offset missing\n");
- goto out;
- }
- xvd.extents[loop].offset = to_number(string);
-
- string = get_string(NULL); /* look for Size */
- if (string == NULL || (*string != 's' && *string != 'S'))
- {
- printk (KERN_ALERT
- "error: extent size missing [%s]. should be \"size\".\n",
- string);
- goto out;
- }
- string = get_string(NULL); /* size */
- if (string == NULL)
- {
- printk (KERN_ALERT "error: extent size missing\n");
- goto out;
- }
- xvd.extents[loop].size = to_number(string);
- }
-
- xenolinux_control_msg(XEN_BLOCK_SEG_CREATE, (char *)&xvd, sizeof(xvd));
-
- out:
- kfree(local);
-
- return res;
-}
-
-static struct file_operations proc_vhd_operations = {
- open: proc_open_vhd,
- read: seq_read,
- llseek: seq_lseek,
- release: seq_release,
- write: proc_write_vhd
-};
-
-/******************************************************************/
-
-int __init xlseg_proc_init(void)
-{
- if ( !(start_info.flags & SIF_PRIVILEGED) )
- return 0;
-
- vhd = create_xeno_proc_entry("vhd", 0600);
- if ( vhd == NULL )
- panic ("xlseg_init: unable to create vhd proc entry\n");
-
- vhd->data = NULL;
- vhd->proc_fops = &proc_vhd_operations;
- vhd->owner = THIS_MODULE;
-
- return 0;
-}
-
-static void __exit xlseg_proc_cleanup(void)
-{
- if ( vhd == NULL ) return;
- remove_xeno_proc_entry("vhd");
- vhd = NULL;
-}
-
-#ifdef MODULE
-module_init(xlseg_proc_init);
-module_exit(xlseg_proc_cleanup);
-#endif
--- /dev/null
+/******************************************************************************
+ * xl_vbd.c
+ *
+ * Xenolinux virtual block-device driver (xvd).
+ *
+ */
+
+#include "xl_block.h"
+
+#define MAJOR_NR XLVIRT_MAJOR
+#include <linux/blk.h>
+
+/* Copied from linux/ide.h */
+typedef unsigned char byte;
+
+#define XLVIRT_MAX 256
+#define XLVIRT_MAJOR_NAME "xvd"
+static int xlvbd_blksize_size[XLVIRT_MAX];
+static int xlvbd_hardsect_size[XLVIRT_MAX];
+static int xlvbd_max_sectors[XLVIRT_MAX];
+
+struct gendisk *xlvbd_gendisk = NULL;
+
+static struct block_device_operations xlvbd_block_fops =
+{
+ open: xenolinux_block_open,
+ release: xenolinux_block_release,
+ ioctl: xenolinux_block_ioctl,
+ check_media_change: xenolinux_block_check,
+ revalidate: xenolinux_block_revalidate,
+};
+
+
+int xlvbd_hwsect(int minor)
+{
+ return xlvbd_hardsect_size[minor];
+}
+
+
+int __init xlvbd_init(xen_disk_info_t *xdi)
+{
+ int i, result, units, minors, disk;
+ struct gendisk *gd;
+
+ SET_MODULE_OWNER(&xlvbd_block_fops);
+
+ result = register_blkdev(XLVIRT_MAJOR, XLVIRT_MAJOR_NAME,
+ &xlvbd_block_fops);
+ if ( result < 0 )
+ {
+ printk(KERN_ALERT "XL VBD: can't get major %d\n", XLVIRT_MAJOR);
+ return result;
+ }
+
+ /* Initialize global arrays. */
+ for (i = 0; i < XLVIRT_MAX; i++)
+ {
+ xlvbd_blksize_size[i] = 512;
+ xlvbd_hardsect_size[i] = 512;
+ xlvbd_max_sectors[i] = 128;
+ }
+
+ blk_size[XLVIRT_MAJOR] = NULL;
+ blksize_size[XLVIRT_MAJOR] = xlvbd_blksize_size;
+ hardsect_size[XLVIRT_MAJOR] = xlvbd_hardsect_size;
+ max_sectors[XLVIRT_MAJOR] = xlvbd_max_sectors;
+ read_ahead[XLVIRT_MAJOR] = 8;
+
+ blk_init_queue(BLK_DEFAULT_QUEUE(XLVIRT_MAJOR), do_xlblk_request);
+
+ /*
+ * Turn off barking 'headactive' mode. We dequeue buffer heads as
+ * soon as we pass them down to Xen.
+ */
+ blk_queue_headactive(BLK_DEFAULT_QUEUE(XLVIRT_MAJOR), 0);
+
+ units = XLVIRT_MAX >> XLVIRT_PARTN_SHIFT;
+
+ /* Construct an appropriate gendisk structure. */
+ minors = units * (1<<XLVIRT_PARTN_SHIFT);
+ gd = kmalloc(sizeof(struct gendisk), GFP_KERNEL);
+ gd->sizes = kmalloc(minors * sizeof(int), GFP_KERNEL);
+ gd->part = kmalloc(minors * sizeof(struct hd_struct), GFP_KERNEL);
+ gd->major = XLVIRT_MAJOR;
+ gd->major_name = XLVIRT_MAJOR_NAME;
+ gd->minor_shift = XLVIRT_PARTN_SHIFT;
+ gd->max_p = 1<<XLVIRT_PARTN_SHIFT;
+ gd->nr_real = units;
+ gd->real_devices = kmalloc(units * sizeof(xl_disk_t), GFP_KERNEL);
+ gd->next = NULL;
+ gd->fops = &xlvbd_block_fops;
+ gd->de_arr = kmalloc(sizeof(*gd->de_arr) * units, GFP_KERNEL);
+ gd->flags = kmalloc(sizeof(*gd->flags) * units, GFP_KERNEL);
+ memset(gd->sizes, 0, minors * sizeof(int));
+ memset(gd->part, 0, minors * sizeof(struct hd_struct));
+ memset(gd->de_arr, 0, sizeof(*gd->de_arr) * units);
+ memset(gd->flags, 0, sizeof(*gd->flags) * units);
+ memset(gd->real_devices, 0, sizeof(xl_disk_t) * units);
+ xlvbd_gendisk = gd;
+ add_gendisk(gd);
+
+ /* Now register each disk in turn. */
+ for ( i = 0; i < xdi->count; i++ )
+ {
+ disk = xdi->disks[i].device & XENDEV_IDX_MASK;
+
+ if ( !IS_VIRTUAL_XENDEV(xdi->disks[i].device) ||
+ (disk >= XLVIRT_DEVS_PER_MAJOR) )
+ continue;
+
+ ((xl_disk_t *)gd->real_devices)[disk].capacity =
+ xdi->disks[i].capacity;
+ register_disk(gd,
+ MKDEV(XLVIRT_MAJOR, disk<<XLVIRT_PARTN_SHIFT),
+ 1<<XLVIRT_PARTN_SHIFT,
+ &xlvbd_block_fops,
+ xdi->disks[i].capacity);
+ }
+
+ printk(KERN_ALERT
+ "XenoLinux Virtual Block Device Driver installed [device: %d]\n",
+ XLVIRT_MAJOR);
+
+ return 0;
+}
+
+
+void xlvbd_cleanup(void)
+{
+ if ( xlvbd_gendisk == NULL ) return;
+
+ blk_cleanup_queue(BLK_DEFAULT_QUEUE(XLVIRT_MAJOR));
+
+ xlvbd_gendisk = NULL;
+
+ read_ahead[XLVIRT_MAJOR] = 0;
+
+ if ( blksize_size[XLVIRT_MAJOR] != NULL )
+ {
+ kfree(blksize_size[XLVIRT_MAJOR]);
+ blksize_size[XLVIRT_MAJOR] = NULL;
+ }
+
+ if ( hardsect_size[XLVIRT_MAJOR] != NULL )
+ {
+ kfree(hardsect_size[XLVIRT_MAJOR]);
+ hardsect_size[XLVIRT_MAJOR] = NULL;
+ }
+
+ if ( max_sectors[XLVIRT_MAJOR] != NULL )
+ {
+ kfree(max_sectors[XLVIRT_MAJOR]);
+ max_sectors[XLVIRT_MAJOR] = NULL;
+ }
+
+ if ( unregister_blkdev(XLVIRT_MAJOR, XLVIRT_MAJOR_NAME) != 0 )
+ {
+ printk(KERN_ALERT
+ "XenoLinux Virtual Block Device Driver"
+ " uninstalled w/ errs\n");
+ }
+}
+
+
+#ifdef MODULE
+module_init(xlvbd_init);
+module_exit(xlvbd_cleanup);
+#endif
#ifdef CONFIG_XENOLINUX_BLOCK
xlblk_init();
- xlseg_init();
- xlseg_proc_init();
#endif
return 0;
#include <linux/blk.h>
#include <linux/slab.h>
#include <linux/genhd.h>
-#include <asm/hypervisor-ifs/block.h>
+#include <asm/hypervisor-ifs/vbd.h>
#include <linux/pagemap.h>
#include "check.h"
return ret;
}
-static inline int HYPERVISOR_block_io_op(void)
+static inline int HYPERVISOR_block_io_op(void *block_io_op)
{
int ret;
__asm__ __volatile__ (
TRAP_INSTR
- : "=a" (ret) : "0" (__HYPERVISOR_block_io_op) );
+ : "=a" (ret) : "0" (__HYPERVISOR_block_io_op),
+ "b" (block_io_op) );
return ret;
}
#if defined(CONFIG_XENOLINUX_BLOCK)
extern int xlblk_init(void);
-extern int xlseg_init(void);
-extern int xlseg_proc_init(void);
#endif /* CONFIG_ARCH_XENO */
extern void set_device_ro(kdev_t dev,int flag);